public async Task EndSequence() { if (status == null) { throw new JobFacInvalidRunStatusException($"Sequence has not been started (instance {jobInstanceKey})"); } currentStep = null; await StoreNewRunStatus(RunStatus.Ended); }
private async Task StartNextStep(int skipToStepNumber = 0) { var stepNum = (skipToStepNumber == 0) ? ++status.JobTypeProperties.SequenceStep : skipToStepNumber; currentStep = steps.Where(s => s.Step == stepNum).FirstOrDefault(); // TODO set correct status and wrap up job processing before throwing if (currentStep == null) { throw new JobFacInvalidDataException($"Step {stepNum} not defined for sequence {jobDefinition.Id}"); } var stepStatus = new StatusSequenceStep { Step = status.JobTypeProperties.SequenceStep }; status.JobTypeProperties.StepStatus.Add(stepNum, stepStatus); if (!await ProcessStartDecision()) { return; } var jobIds = Formatting.SplitCommaSeparatedList(currentStep.JobDefinitionIdList); foreach (var id in jobIds) { var options = new FactoryStartOptions { DefinitionId = id, SequenceInstanceId = jobInstanceKey, // TODO filter spawned-job args/payloads to the specific job? ReplacementArguments = status.StartOptions.ReplacementArguments, StartupPayloads = status.StartOptions.StartupPayloads }; var jobId = await jobFactory.StartJob(options); status.JobTypeProperties.JobInstanceStepMap.Add(jobId, stepNum); stepStatus.JobStatus.Add(jobId, new JobStatus <StatusExternalProcess> { Key = jobId, StartOptions = options, RunStatus = RunStatus.Unknown, }); } await StoreNewRunStatus(RunStatus.Running); if (currentStep.ExitDecision == StepExitDecision.DoNextStepWithoutWaiting) { await StartNextStep(); } // local function returns value indicating whether to continue start-up async Task <bool> ProcessStartDecision() { // The validator ensures StartDates and StartTimes are correct. if (currentStep.StartDateDecision != StepStartDateDecision.NoDecision) { var analysis = DateTimeAnalysis.Now(currentStep.StartDecisionTimeZone); var dates = Formatting.SplitCommaSeparatedList(currentStep.StartDates); bool startDecision = currentStep.StartDateDecision switch { // see scheduler TargetPlanner for descriptions StepStartDateDecision.DaysOfWeek => analysis.InDaysOfWeek(dates), StepStartDateDecision.DaysOfMonth => analysis.InDaysOfMonth(dates), StepStartDateDecision.SpecificDates => analysis.InSpecificDates(dates), StepStartDateDecision.DateRanges => analysis.InDateRanges(dates), StepStartDateDecision.Weekdays => analysis.InWeekdays(dates), _ => true, }; if (startDecision && currentStep.StartTimeDecision != StepStartTimeDecision.NoDecision) { var times = Formatting.SplitCommaSeparatedList(currentStep.StartTimes); startDecision = currentStep.StartTimeDecision switch { StepStartTimeDecision.IfHours => analysis.InHours(times), StepStartTimeDecision.IfMinutes => analysis.InMinutes(times), StepStartTimeDecision.IfTime => analysis.InSpecificTimes(times), StepStartTimeDecision.IfTimeRange => analysis.InTimeRanges(times), _ => true, }; } stepStatus.StartDecisionSuccess = startDecision; if (!startDecision) { await historyRepo.UpdateStatus(status); switch (currentStep.StartFalseAction) { case StepAction.DoNextStep: await StartNextStep(); break; case StepAction.DoStepNumber: await StartNextStep(currentStep.StartFalseStepNumber); break; case StepAction.EndSequence: await Stop(); break; } return(false); } } return(true); } }