/// <summary> /// /// </summary> StepInfo GetStepFromHistory(WorkflowStepElement stepConfig) { foreach (StepInfo s in _stepHistory) { // Check whether the next step hasn't been added already if (s.StepConfig == stepConfig) { return(s); } } return(null); }
void OnChildServiceRequested(int stepNumber, int attemptNumber, SettingsCollection options) { // Get the step configuration elements WorkflowStepElement stepConfig = this.Configuration.Workflow[stepNumber]; AccountServiceSettingsElement stepSettings = this.Configuration.StepSettings != null ? this.Configuration.StepSettings[stepConfig] : null; // Take the step configuration ActiveServiceElement configuration = stepSettings != null ? new ActiveServiceElement(stepSettings) : new ActiveServiceElement(stepConfig); // Add child-specific options if (options != null) { configuration.Options.Merge(options); } // Add parent options, without overriding child options with the same name foreach (var parentOption in this.Configuration.Options) { if (!configuration.Options.ContainsKey(parentOption.Key)) { configuration.Options.Add(parentOption.Key, parentOption.Value); } } // Add parent extensions, without overriding child options with the same name foreach (var parentExtension in this.Configuration.Extensions) { if (!configuration.Extensions.ContainsKey(parentExtension.Key)) { configuration.Extensions.Add(parentExtension.Key, parentExtension.Value); } } // Generate a child instance ServiceInstance child = Service.CreateInstance(configuration, this, this.AccountID); child.StateChanged += _childStateHandler; child.OutcomeReported += _childOutcomeHandler; child.ProgressReported += _childProgressHandler; _childServices.Add(child, stepNumber); if (ChildServiceRequested != null) { ChildServiceRequested(this, new ServiceRequestedEventArgs(child, attemptNumber)); } }
public AccountServiceSettingsElement this[WorkflowStepElement step] { get { foreach (AccountServiceSettingsElement elem in this) { if (elem.Step.Element == step) { return(elem); } } return(null); } }
/// <summary> /// /// </summary> /// <param name="nextStepConfig"></param> /// <returns></returns> bool IsInStepHistory(WorkflowStepElement nextStepConfig) { bool alreadyAdded = false; foreach (StepInfo s in _stepHistory) { // Check whether the next step hasn't been added already if (s.StepConfig == nextStepConfig) { alreadyAdded = true; break; } } return(alreadyAdded); }
/// <summary> /// Gets the next step that is enabled and is not a failure handler. If there is none returns null. /// </summary> WorkflowStepElement GetNextStep(WorkflowStepElement stepConfig) { int indexOfCurrent = stepConfig == null ? 0 : Instance.Configuration.Workflow.IndexOf(stepConfig) + 1; // Find the next non-failure handler step WorkflowStepElement next = null; for (int i = indexOfCurrent; i < Instance.Configuration.Workflow.Count; i++) { WorkflowStepElement step = Instance.Configuration.Workflow[i]; if ( step.IsEnabled && !step.IsFailureHandler // && //IsStepConditionValid(step.ConditionOptions, step.Condition) ) { next = Instance.Configuration.Workflow[i]; break; } } return(next); }
public ServiceDisplayInfo(ServiceElement configuration, WorkflowStepElement step) : this(configuration, step.Name) { _step = step; }
/// <summary> /// /// </summary> protected virtual ServiceOutcome DoWork() { if (Outcome != ServiceOutcome.Unspecified || State != ServiceState.Running) { throw new InvalidOperationException("DoWork() cannot be called because the service has ended."); } // Simulate processing execution time if (Instance.Configuration.DebugDelay != TimeSpan.Zero) { Thread.Sleep(Instance.Configuration.DebugDelay); } // Service with no steps means instant success! if (Instance.Configuration.Workflow.Count < 1) { return(ServiceOutcome.Success); } // Add the first step of the history as null - indicator for starting if (_stepHistory.Count < 1) { _stepHistory.Add(null); } // The return result bool stepsInProgress = false; ServiceOutcome outcome = ServiceOutcome.Unspecified; // Loop over each step in the history foreach (StepInfo step in _stepHistory.ToArray()) { bool moveToNextStep = true; if (step != null) { stepsInProgress = stepsInProgress || step.ServiceState != ServiceState.Ended; // As long as a blocking process is running, halt all processing if (stepsInProgress && step.Config.IsBlocking) { break; } // Indicates whether to process next step moveToNextStep = step.ServiceOutcome == ServiceOutcome.Success; if (!step.FailureWasHandled && (step.ServiceOutcome == ServiceOutcome.Failure || step.ServiceOutcome == ServiceOutcome.Aborted)) { if (step.FailureRepetitions < step.Config.FailureRepeat - 1 && step.ServiceOutcome != ServiceOutcome.Aborted) { step.ServiceState = ServiceState.Uninitialized; step.FailureRepetitions++; } else { if (step.Config.FailureOutcome == FailureOutcome.Continue) { // Process same as Success moveToNextStep = true; } // This here is due to base[] getter bug else if ( !step.Config.IsFailureHandler && step.Config.FailureHandler.Element != null && step.Config.FailureHandler.Element.BaseConfiguration.Element.Name != null && !IsInStepHistory(step.Config.FailureHandler.Element) //&& //IsStepConditionValid(step.Config.FailureHandler.Element.ConditionOptions, step.Config.FailureHandler.Element.Condition) ) { // Get the correct step element AccountServiceSettingsElement stepSettings = Instance.Configuration.StepSettings != null ? Instance.Configuration.StepSettings[step.Config.FailureHandler.Element] : null; // Add a new step, the failure handler if (stepSettings != null) { _stepHistory.Add(new StepInfo(stepSettings)); } else { _stepHistory.Add(new StepInfo(step.Config.FailureHandler.Element)); } // Done handling this step's failure step.FailureWasHandled = true; } else { // Terminate because there is no failure handling - abort and stop processing outcome = ServiceOutcome.Failure; break; } } } } if (moveToNextStep) { // Get rid of the first null used to jump start the processing loop if (step == null) { _stepHistory.Remove(step); } // Get the next step of a failure handler WorkflowStepElement nextStepConfig = GetNextStep(step == null ? null : step.StepConfig); if (nextStepConfig == null) { // No steps left to process if (_stepHistory.TrueForAll(new Predicate <StepInfo>(delegate(StepInfo s) { return(s.ServiceState == ServiceState.Ended); }))) { // All steps ended - outcome successful outcome = ServiceOutcome.Success; break; } else { // There are still steps being run so wait for them to complete before reporting that we are done continue; } } else if (nextStepConfig.WaitForPrevious && stepsInProgress) { // The next step needs to wait for all previous steps to end - stop processing break; } else { bool adding = true; while (adding) { if (!IsInStepHistory(nextStepConfig)) { // Get the correct step element AccountServiceSettingsElement stepSettings = Instance.Configuration.StepSettings != null ? Instance.Configuration.StepSettings[nextStepConfig] : null; // Schedule the next step as long as it hasn't been added already if (stepSettings != null) { _stepHistory.Add(new StepInfo(stepSettings)); } else { _stepHistory.Add(new StepInfo(nextStepConfig)); } } // If the step is blocking or if it's a failure handler, stop adding steps, otherwise add the next if (nextStepConfig.IsBlocking || nextStepConfig == Instance.Configuration.Workflow[Instance.Configuration.Workflow.Count - 1]) { adding = false; } else { nextStepConfig = GetNextStep(nextStepConfig); // Only add the next if it doesn't require previous steps to end first if (nextStepConfig == null || nextStepConfig.WaitForPrevious) { adding = false; } } } } } } if (outcome == ServiceOutcome.Unspecified) { // Request any pending child steps to be run foreach (StepInfo step in _stepHistory) { if (step.ServiceState == ServiceState.Uninitialized) { RequestChildService(Instance.Configuration.Workflow.IndexOf(step.StepConfig), step.FailureRepetitions + 1); } } } return(outcome); }
/// <summary> /// /// </summary> public StepInfo(WorkflowStepElement stepConfig) { StepConfig = stepConfig; Config = new ActiveWorkflowStepElement(StepConfig); }
/*=========================*/ #endregion #region Constructors /*=========================*/ /// <summary> /// /// </summary> public StepInfo(AccountServiceSettingsElement accountStepConfig) { StepConfig = accountStepConfig.Step.Element; AccountStepConfig = accountStepConfig; Config = new ActiveWorkflowStepElement(AccountStepConfig); }