throttleChan = make(chan struct{}, numOfConcurrentMonitorSteps) doneChan = make(chan struct{}, 1) fakeStep = new(fakes.FakeStep) fakeStep.PerformStub = func() error { throttleChan <- struct{}{} <-doneChan return nil } checkFunc = func() steps.Step { return fakeStep } }) AfterEach(func() { step.Cancel() }) It("throttles concurrent health check", func() { for i := 0; i < 5; i++ { go step.Perform() } Consistently(fakeStep.PerformCallCount).Should(Equal(0)) clock.Increment(501 * time.Millisecond) Eventually(func() int { return len(throttleChan) }).Should(Equal(numOfConcurrentMonitorSteps)) Consistently(func() int { return len(throttleChan)
func (store *GardenStore) runStepProcess( logger lager.Logger, step steps.Step, hasStartedRunning <-chan struct{}, gardenContainer garden.Container, guid string, ) { process := ifrit.Invoke(ifrit.RunFunc(func(signals <-chan os.Signal, ready chan<- struct{}) error { logger := logger.Session("run-step-process") logger.Info("started") defer logger.Info("finished") seqComplete := make(chan error) close(ready) go func() { seqComplete <- step.Perform() }() result := executor.ContainerRunResult{} toldToStop := false OUTER_LOOP: for { select { case <-signals: signals = nil toldToStop = true logger.Info("signaled") step.Cancel() case <-hasStartedRunning: hasStartedRunning = nil logger.Info("transitioning-to-running") err := store.transitionToRunning(logger, gardenContainer) if err != nil { logger.Error("failed-transitioning-to-running", err) result.Failed = true result.FailureReason = err.Error() break OUTER_LOOP } logger.Info("succeeded-transitioning-to-running") case err := <-seqComplete: if err == nil { logger.Info("step-finished-normally") } else if toldToStop { logger.Info("step-cancelled") result.Stopped = true } else { logger.Info("step-finished-with-error", lager.Data{"error": err.Error()}) result.Failed = true result.FailureReason = err.Error() } break OUTER_LOOP } } logger.Info("transitioning-to-complete") err := store.transitionToComplete(logger, gardenContainer, result) if err != nil { logger.Error("failed-transitioning-to-complete", err) return nil } logger.Info("succeeded-transitioning-to-complete") return nil })) store.processesL.Lock() store.runningProcesses[guid] = process numProcesses := len(store.runningProcesses) store.processesL.Unlock() logger.Info("stored-step-process", lager.Data{"num-step-processes": numProcesses}) }