Esempio n. 1
0
// watchRelationUnits starts watching the relation units for the given
// relation, waits for its first event, and records the information in
// the current snapshot.
func (w *RemoteStateWatcher) watchRelationUnits(
	rel Relation, relationTag names.RelationTag, ruw watcher.RelationUnitsWatcher,
) error {
	relationSnapshot := RelationSnapshot{
		Life:    rel.Life(),
		Members: make(map[string]int64),
	}
	select {
	case <-w.catacomb.Dying():
		return w.catacomb.ErrDying()
	case change, ok := <-ruw.Changes():
		if !ok {
			return errors.New("relation units watcher closed")
		}
		for unit, settings := range change.Changed {
			relationSnapshot.Members[unit] = settings.Version
		}
	}
	innerRUW, err := newRelationUnitsWatcher(rel.Id(), ruw, w.relationUnitsChanges)
	if err != nil {
		return errors.Trace(err)
	}
	if err := w.catacomb.Add(innerRUW); err != nil {
		return errors.Trace(err)
	}
	w.current.Relations[rel.Id()] = relationSnapshot
	w.relations[relationTag] = innerRUW
	return nil
}
Esempio n. 2
0
// newRelationUnitsWatcher creates a new worker that takes values from the
// supplied watcher's Changes chan, annotates them with the supplied relation
// id, and delivers then on the supplied out chan.
//
// The caller releases responsibility for stopping the supplied watcher and
// waiting for errors, *whether or not this method succeeds*.
func newRelationUnitsWatcher(
	relationId int,
	watcher watcher.RelationUnitsWatcher,
	out chan<- relationUnitsChange,
) (*relationUnitsWatcher, error) {
	ruw := &relationUnitsWatcher{
		relationId: relationId,
		changes:    watcher.Changes(),
		out:        out,
	}
	err := catacomb.Invoke(catacomb.Plan{
		Site: &ruw.catacomb,
		Work: ruw.loop,
		Init: []worker.Worker{watcher},
	})
	if err != nil {
		return nil, errors.Trace(err)
	}
	return ruw, nil
}