// 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 }
// 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 }