func (s *ManifoldSuite) TestOutputSuccess(c *gc.C) { w := s.mustStartManifold(c) var stTracker workerstate.StateTracker err := s.manifold.Output(w, &stTracker) c.Assert(err, jc.ErrorIsNil) st, err := stTracker.Use() c.Assert(err, jc.ErrorIsNil) c.Check(st, gc.Equals, s.State) c.Assert(stTracker.Done(), jc.ErrorIsNil) // Ensure State is closed when the worker is done. checkStop(c, w) assertStateClosed(c, s.State) }
func (s *ManifoldSuite) TestStateStillInUse(c *gc.C) { w := s.mustStartManifold(c) var stTracker workerstate.StateTracker err := s.manifold.Output(w, &stTracker) c.Assert(err, jc.ErrorIsNil) st, err := stTracker.Use() c.Assert(err, jc.ErrorIsNil) // Close the worker while the State is still in use. checkStop(c, w) assertStateNotClosed(c, st) // Now signal that the State is no longer needed. c.Assert(stTracker.Done(), jc.ErrorIsNil) assertStateClosed(c, st) }
// StateWorkersManifold starts workers that rely on a *state.State // using a function provided to it. // // This manifold exists to start State-using workers which have not // yet been ported to work directly with the dependency engine. Once // all state workers started by StartStateWorkers have been migrated // to the dependency engine, this manifold can be removed. func StateWorkersManifold(config StateWorkersConfig) dependency.Manifold { return dependency.Manifold{ Inputs: []string{ config.StateName, }, Start: func(context dependency.Context) (worker.Worker, error) { if config.StartStateWorkers == nil { return nil, errors.New("StartStateWorkers not specified") } var stTracker workerstate.StateTracker if err := context.Get(config.StateName, &stTracker); err != nil { return nil, err } st, err := stTracker.Use() if err != nil { return nil, errors.Annotate(err, "acquiring state") } w, err := config.StartStateWorkers(st) if err != nil { stTracker.Done() return nil, errors.Annotate(err, "worker startup") } // When the state workers are done, indicate that we no // longer need the State. go func() { w.Wait() stTracker.Done() }() return w, nil }, } }