func (instance *Execution) doUnregisterExecution(target *service.Execution) { instance.doWLock() defer instance.doWUnlock() delete(instance.executions, target.Service()) delete(instance.restartRequests, target.Service()) instance.wg.Done() }
func (instance *Execution) delayedStartIfNeeded(target *service.Execution, currentRun int) bool { config := target.Service().Config() if currentRun == 1 { return instance.delayedStartIfNeededFor(target, config.StartDelayInSeconds, "Wait %d seconds before starting...") } return instance.delayedStartIfNeededFor(target, config.RestartDelayInSeconds, "Wait %d seconds before restarting...") }
func (instance *Execution) drive(target *service.Execution) { var exitCode values.ExitCode var err error defer instance.doAfterExecution(target, exitCode, err) respectDelay := true doRun := true for run := 1; doRun && target != nil && !instance.isAlreadyStopRequested(target); run++ { if respectDelay { if !instance.delayedStartIfNeeded(target, run) { break } } else { run = 1 } if !instance.isAlreadyStopRequested(target) { exitCode, err = target.Run() doRun, respectDelay = instance.checkAfterExecutionStates(target, exitCode, err) if doRun && !instance.isAlreadyStopRequested(target) { newTarget, err := instance.recreateExecution(target) if err != nil { instance.executable.Logger().LogProblem(err, logger.Error, "Could not retrigger execution of '%v'.", target) } else { target = newTarget } } } } }
func (instance *Execution) delayedStartIfNeededFor(target *service.Execution, delayInSeconds values.NonNegativeInteger, messagePattern string) bool { s := target.Service() if s.Config().StartDelayInSeconds > 0 { s.Logger().Log(logger.Debug, messagePattern, delayInSeconds) return target.SyncGroup().Sleep(time.Duration(delayInSeconds)*time.Second) == nil } return true }
func (instance *Execution) doAfterExecution(target *service.Execution, exitCode values.ExitCode, err error) { defer instance.doUnregisterExecution(target) if target.Service().Config().Type == service.Master { instance.masterExitCode = &exitCode instance.masterError = err instance.stopOthers() } }
func (instance *Execution) recreateExecution(target *service.Execution) (*service.Execution, error) { instance.doWLock() defer instance.doWUnlock() s := target.Service() newTarget, err := s.NewExecution(instance.executable.KeyStore()) if err != nil { delete(instance.executions, s) } else { instance.executions[s] = newTarget } delete(instance.restartRequests, s) return newTarget, err }
func (instance *Execution) checkAfterExecutionStates(target *service.Execution, exitCode values.ExitCode, err error) (doRestart bool, respectDelay bool) { if _, ok := err.(service.StoppedOrKilledError); ok { doRestart = false } else if _, ok := err.(service.UnrecoverableError); ok { doRestart = target.Service().Config().CronExpression.IsEnabled() && instance.masterExitCode == nil } else if instance.checkRestartRequestedAndClean(target.Service()) { doRestart = true respectDelay = false } else if target.Service().Config().SuccessExitCodes.Contains(exitCode) { doRestart = (target.Service().Config().CronExpression.IsEnabled() && instance.masterExitCode == nil) || target.Service().Config().AutoRestart.OnSuccess() } else { doRestart = target.Service().Config().AutoRestart.OnFailures() respectDelay = true } return doRestart, respectDelay }
func (instance *Execution) isAlreadyStopRequested(target *service.Execution) bool { instance.doRLock() defer instance.doRUnlock() stopRequested, ok := instance.stopRequests[target.Service()] return ok && stopRequested }