Ejemplo n.º 1
0
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
}
Ejemplo n.º 2
0
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
}