// upgradeWaiterWorker runs the specified worker after upgrades have completed. func (a *MachineAgent) upgradeWaiterWorker(start func() (worker.Worker, error)) worker.Worker { return worker.NewSimpleWorker(func(stop <-chan struct{}) error { // wait for the upgrade to complete (or for us to be stopped) select { case <-stop: return nil case <-a.upgradeComplete: } w, err := start() if err != nil { return err } waitCh := make(chan error) go func() { waitCh <- w.Wait() }() select { case err := <-waitCh: return err case <-stop: w.Kill() } return <-waitCh }) }
func (s *singularSuite) TestWithIsMasterTrue(c *gc.C) { // When IsMaster returns true, workers get started on the underlying // runner as usual. s.PatchValue(&singular.PingInterval, 1*time.Millisecond) underlyingRunner := newRunner() conn := &fakeConn{ isMaster: true, } r, err := singular.New(underlyingRunner, conn) c.Assert(err, gc.IsNil) started := make(chan struct{}, 1) err = r.StartWorker("worker", func() (worker.Worker, error) { return worker.NewSimpleWorker(func(stop <-chan struct{}) error { started <- struct{}{} <-stop return nil }), nil }) select { case <-started: case <-time.After(testing.LongWait): c.Fatalf("timed out waiting for worker to start") } err = worker.Stop(r) c.Assert(err, gc.IsNil) }
func (a *agent) mongoWorker() (worker.Worker, error) { dialInfo := testing.MgoDialInfo(a.hostPort) session, err := mgo.DialWithInfo(dialInfo) if err != nil { return nil, err } mc := &mongoConn{ localHostPort: a.hostPort, session: session, } runner := worker.NewRunner( connectionIsFatal(mc), func(err0, err1 error) bool { return true }, ) singularRunner, err := singular.New(runner, mc) if err != nil { return nil, fmt.Errorf("cannot start singular runner: %v", err) } a.notify.workerConnected() singularRunner.StartWorker(fmt.Sprint("worker-", a.notify.id), func() (worker.Worker, error) { return worker.NewSimpleWorker(func(stop <-chan struct{}) error { return a.worker(session, stop) }), nil }) return runner, nil }
// upgradeWorker runs the required upgrade operations to upgrade to the current Juju version. func (a *MachineAgent) upgradeWorker( apiState *api.State, jobs []params.MachineJob, agentConfig agent.Config, ) worker.Worker { return worker.NewSimpleWorker(func(stop <-chan struct{}) error { select { case <-a.upgradeComplete: // Our work is already done (we're probably being restarted // because the API connection has gone down), so do nothing. <-stop return nil default: } // If the machine agent is a state server, wait until state is opened. needsState := false for _, job := range jobs { if job == params.JobManageEnviron { needsState = true } } // We need a *state.State for upgrades. We open it independently // of StateWorker, because we have no guarantees about when // and how often StateWorker might run. var st *state.State if needsState { var err error info, ok := agentConfig.StateInfo() if !ok { return fmt.Errorf("no state info available") } st, err = state.Open(info, state.DialOpts{}, environs.NewStatePolicy()) if err != nil { return err } defer st.Close() } err := a.runUpgrades(st, apiState, jobs, agentConfig) if err != nil { return err } logger.Infof("upgrade to %v completed.", version.Current) close(a.upgradeComplete) <-stop return nil }) }
func (r *runner) StartWorker(id string, startFunc func() (worker.Worker, error)) error { if r.isMaster { // We are master; the started workers should // encounter an error as they do what they're supposed // to do - we can just start the worker in the // underlying runner. logger.Infof("starting %q", id) return r.Runner.StartWorker(id, startFunc) } logger.Infof("standby %q", id) // We're not master, so don't start the worker, but start a pinger so // that we know when the connection master changes. r.startPingerOnce.Do(func() { go r.pinger() }) return r.Runner.StartWorker(id, func() (worker.Worker, error) { return worker.NewSimpleWorker(r.waitPinger), nil }) }
// newStateStarterWorker wraps stateStarter in a simple worker for use in // a.runner.StartWorker. func (a *MachineAgent) newStateStarterWorker() (worker.Worker, error) { return worker.NewSimpleWorker(a.stateStarter), nil }
func newDummyWorker() worker.Worker { return worker.NewSimpleWorker(func(stop <-chan struct{}) error { <-stop return nil }) }