func (b *etcdBackend) SetServiceMeta(service string, meta *discoverd.ServiceMeta) error { serviceKey := b.serviceKey(service) _, err := b.etcd.Get(serviceKey, false, false) if isEtcdNotFound(err) { return NotFoundError{Service: service} } if err != nil { return err } var res *etcd.Response key := path.Join(serviceKey, "meta") if meta.Index == 0 { res, err = b.etcd.Create(key, string(meta.Data), 0) if isEtcdExists(err) { err = hh.ObjectExistsErr(fmt.Sprintf("Service metadata for %q already exists, use index=n to set", service)) } } else { res, err = b.etcd.CompareAndSwap(key, string(meta.Data), 0, "", meta.Index) if isEtcdNotFound(err) { err = hh.PreconditionFailedErr(fmt.Sprintf("Service metadata for %q does not exist, use index=0 to set", service)) } else if isEtcdCompareFailed(err) { err = hh.PreconditionFailedErr(fmt.Sprintf("Service metadata for %q exists, but wrong index provided", service)) } } if err != nil { return err } meta.Index = res.Node.ModifiedIndex return nil }
func (s *Store) applySetServiceMetaCommand(cmd []byte, index uint64) error { var c setServiceMetaCommand if err := json.Unmarshal(cmd, &c); err != nil { return err } // Verify that the service exists. service := s.data.Services[c.Service] if service == nil { return NotFoundError{Service: c.Service} } // If no index is provided then the meta should not be set. curr := s.data.Metas[c.Service] if c.Meta.Index == 0 { if curr != nil { return hh.ObjectExistsErr(fmt.Sprintf("Service metadata for %q already exists, use index=n to set", c.Service)) } } else { if curr == nil { return hh.PreconditionFailedErr(fmt.Sprintf("Service metadata for %q does not exist, use index=0 to set", c.Service)) } else if curr.Index != c.Meta.Index { return hh.PreconditionFailedErr(fmt.Sprintf("Service metadata for %q exists, but wrong index provided", c.Service)) } } leaderID := c.Meta.LeaderID c.Meta.LeaderID = "" // Update the meta and set the index. c.Meta.Index = index s.data.Metas[c.Service] = c.Meta if leaderID != "" { // If a new leader was included in the meta update, apply it s.data.Leaders[c.Service] = leaderID } // Broadcast EventKindServiceMeta event. s.broadcast(&discoverd.Event{ Service: c.Service, Kind: discoverd.EventKindServiceMeta, ServiceMeta: c.Meta, }) if leaderID != "" { // Broadcast leader update, if the new instance exists if inst := s.data.Instances[c.Service][leaderID]; inst != nil { s.broadcast(&discoverd.Event{ Service: c.Service, Kind: discoverd.EventKindLeader, Instance: inst, }) } } return nil }