func (e *Etcd) watchRing(r torus.Ring) { ctx, cancel := context.WithCancel(e.getContext()) defer cancel() wch := e.Client.Watch(ctx, MkKey("meta", "the-one-ring")) for resp := range wch { if err := resp.Err(); err != nil { clog.Errorf("error watching ring: %s", err) return } for _, ev := range resp.Events { newRing, err := ring.Unmarshal(ev.Kv.Value) if err != nil { clog.Debugf("corrupted ring: %#v", ev.Kv.Value) clog.Errorf("Failed to unmarshal ring: %s", err) clog.Error("corrupted ring? Continuing with current ring") continue } clog.Infof("got new ring") if r.Version() == newRing.Version() { clog.Warningf("Same ring version: %d", r.Version()) } e.mut.RLock() for _, x := range e.ringListeners { x <- newRing } r = newRing e.mut.RUnlock() } } }
func setRing(cfg torus.Config, r torus.Ring) error { client, err := etcdv3.New(etcdv3.Config{Endpoints: []string{cfg.MetadataAddress}, TLS: cfg.TLS}) if err != nil { return err } defer client.Close() resp, err := client.Get(context.Background(), MkKey("meta", "the-one-ring")) if err != nil { return err } if len(resp.Kvs) == 0 { return torus.ErrNoGlobalMetadata } oldr, err := ring.Unmarshal(resp.Kvs[0].Value) if err != nil { return err } if oldr.Version() != r.Version()-1 { return torus.ErrNonSequentialRing } b, err := r.Marshal() if err != nil { return err } _, err = client.Put(context.Background(), MkKey("meta", "the-one-ring"), string(b)) return err }
func (c *etcdCtx) getRing() (torus.Ring, int64, error) { promOps.WithLabelValues("get-ring").Inc() resp, err := c.etcd.Client.Get(c.getContext(), MkKey("meta", "the-one-ring")) if err != nil { return nil, 0, err } if len(resp.Kvs) == 0 { return nil, 0, torus.ErrNoGlobalMetadata } ring, err := ring.Unmarshal(resp.Kvs[0].Value) if err != nil { return nil, 0, err } return ring, resp.Kvs[0].Version, nil }