/// <summary> /// Sets up a new activity or child workflow as specified by the workflow at the start of the workflow. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnWorkflowExecutionStarted(WorkflowDecisionContext context) { var activityState = BuildActivityState(context); if (WorkflowSteps == null || WorkflowSteps.Length == 0) { return CompleteWorkflow(""); } // Since this is the start of the workflow execution, we start off with the first item // in the workflow steps RespondDecisionTaskCompletedRequest decisionRequest; if (WorkflowSteps[0].IsActivity()) { var activity = ((WorkflowActivitySetupContext) WorkflowSteps[0]).Clone(); Debug.Assert(activity != null, "activity != null"); // If input string is empty, we pass the input from the caller (in this case, workflow // execution start) to the activity if (String.IsNullOrEmpty(activity.Input)) { activity.Input = activityState; } decisionRequest = ScheduleActivityTask(activity); } else if (WorkflowSteps[0].IsTimer()) { var timer = ((WorkflowTimerSetupContext) WorkflowSteps[0]).Clone(); Debug.Assert(timer != null, "timer != null"); decisionRequest = StartTimer(timer); } else if (WorkflowSteps[0].IsWorkflow()) { var childWorkflow = ((WorkflowSetupContext) WorkflowSteps[0]).Clone(); Debug.Assert(childWorkflow != null, "childWorkflow != null"); // If input string is empty, we pass the input from the caller (in this case, workflow // execution start) to the activity if (String.IsNullOrEmpty(childWorkflow.Input)) { childWorkflow.Input = activityState; } decisionRequest = StartChildWorkflowExecution(childWorkflow); } else { throw new Exception("We can only have activity, timer, or workflow as workflow steps"); } return decisionRequest; }
/// <summary> /// Constructor for the workflow event processor. /// </summary> /// <param name="decisionTask">Decision task passed in from SWF as decision task response.</param> /// <param name="workflows">IEnumerable set of string for workflow name and Type for workflow class.</param> /// <param name="request">The request used to retrieve <paramref name="decisionTask"/>, which will be used to retrieve subsequent history event pages.</param> /// <param name="swfClient">An SWF client.</param> public WorkflowEventsProcessor(DecisionTask decisionTask, IEnumerable<KeyValuePair<string, Type>> workflows, PollForDecisionTaskRequest request, IAmazonSimpleWorkflow swfClient) { // Decision task can't be null. if (decisionTask == null) { throw new ArgumentNullException("decisionTask"); } if (request == null) { throw new ArgumentNullException("request"); } // Store the decision task and allocate a new decision context and event dictionary which // we will use as we walk through the chain of events _decisionTask = decisionTask; _request = request; _decisionContext = new WorkflowDecisionContext(); _swfClient = swfClient; // Set up our events data structure _events = new WorkflowEventsIterator(ref decisionTask, _request, _swfClient); _workflows = (Dictionary<string, Type>) workflows; }
/// <summary> /// Builds the activity state object to pass to the activity. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>The activity state.</returns> protected string BuildActivityState(WorkflowDecisionContext context) { var activityState = new ActivityState { StartingInput = context.StartingInput, PreviousResult = context.Result }; return JsonConvert.SerializeObject(activityState); }
private RespondDecisionTaskCompletedRequest GetNextRequest(ISetupContext nextStep, WorkflowDecisionContext context, string nextInput) { // If we don't have anymore steps, complete the workflow if (nextStep == null) { return CompleteWorkflow(context.Result); } // Found another step if (nextStep.IsActivity()) { // Next step is an activity, set up a schedule activity decision var activity = ((WorkflowActivitySetupContext) nextStep).Clone(); activity.Input = nextInput; return ScheduleActivityTask(activity); } if (nextStep.IsTimer()) { // Next step is a timer, set up a start timer decision var timer = ((WorkflowTimerSetupContext) nextStep).Clone(); return StartTimer(timer); } // Next step is not an activity, set up a child workflow decision Debug.Assert(nextStep.IsWorkflow(), "Steps can only be activities, timers, or workflows."); var workflow = ((WorkflowSetupContext) nextStep).Clone(); workflow.Input = nextInput; return StartChildWorkflowExecution(workflow); }
public RespondDecisionTaskCompletedRequest OnTimerCanceled(WorkflowDecisionContext context) { var step = ((WorkflowTimerSetupContext) GetStep(false /* activity completion */, true /* is timer */, context.TimerId, null /* step version */)); switch (step.CancelAction) { case TimerCanceledAction.CompleteWorkflow: return CompleteWorkflow(context.Result); case TimerCanceledAction.CancelWorkflow: return CancelWorkflow(context.Details); case TimerCanceledAction.ProceedToNextActivity: var nextStep = GetNextStep(false /* activity completion */, true /* is timer */, context.TimerId, null); var activityState = BuildActivityState(context); return GetNextRequest(nextStep, context, activityState); default: throw new InvalidOperationException(); } }
public RespondDecisionTaskCompletedRequest OnTimerFired(WorkflowDecisionContext context) { // Fetch the next step var nextStep = GetNextStep(false /* activity completion */, true /* is timer */, context.TimerId, null); var activityState = BuildActivityState(context); return GetNextRequest(nextStep, context, activityState); }
public RespondDecisionTaskCompletedRequest OnTimerStarted(WorkflowDecisionContext context) { return EmptyDecision(); }
public virtual RespondDecisionTaskCompletedRequest OnWorkflowExecutionCancelRequested(WorkflowDecisionContext context) { return CancelWorkflow(context.Details); }
/// <summary> /// Re-tries the child workflow 3 times before failing the workflow. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnChildWorkflowExecutionTimedOut(WorkflowDecisionContext context) { var timeoutCount = 0; // If we have already re-tried 3 times, fail the workflow if (context.Markers.ContainsKey("ChildWorkflowTimeoutMarker")) { timeoutCount = Int32.Parse(context.Markers["ChildWorkflowTimeoutMarker"]); if (timeoutCount > 3) { return FailWorkflow("Failing workflow after 3 retry attempts.", "OnChildWorkflowExecutionTimedOut"); } } // Fetch the next step and set it up with the right input and doubled timeout value var workflowStep = ((WorkflowSetupContext) GetStep(false /* workflow timed out */, false /* is timer */, context.ChildWorkflowName, context.ChildWorkflowVersion)).Clone(); switch (context.TimeoutType) { case "START_TO_CLOSE": workflowStep.ExecutionStartToCloseTimeout = (Int32.Parse(workflowStep.ExecutionStartToCloseTimeout) * 1 /*timeoutCount*/).ToString(CultureInfo.InvariantCulture); break; default: Debug.Assert(false, "Unknown timeout type " + context.TimeoutType); break; } if (String.IsNullOrEmpty(workflowStep.Input)) { workflowStep.Input = ""; } // Fetch the decision to start the child workflow execution var request = StartChildWorkflowExecution(workflowStep); // Fetch the decision for a new timeout marker and add it to the child workflow request var marker = RecordMarker(timeoutCount.ToString(CultureInfo.InvariantCulture), "ChildWorkflowTimeoutMarker"); request.Decisions.Add(marker.Decisions[0]); // Return the combined request return request; }
/// <summary> /// Set up a fail workflow decision in the event of a failure of scheduling a task. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnChildWorkflowExecutionCompleted(WorkflowDecisionContext context) { // Fetch the next step var nextStep = GetNextStep(false /* workflow completion */, false /* is timer */, context.ChildWorkflowName, context.ChildWorkflowVersion); var activityState = BuildActivityState(context); return GetNextRequest(nextStep, context, activityState); }
/// <summary> /// Handles the child workflow execution started by returning an empty decision. This could be modified in the /// future to handle parallel child workflow/activity invocations. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnChildWorkflowExecutionStarted(WorkflowDecisionContext context) { return EmptyDecision(); }
/// <summary> /// Set up a fail workflow decision in the event of a failure of scheduling a task. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnScheduleActivityTaskFailed(WorkflowDecisionContext context) { return FailWorkflow(context.Cause, "OnScheduleActivityTaskFailed"); }
/// <summary> /// Re-tries the activity 3 times before failing the workflow. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnActivityTaskTimedOut(WorkflowDecisionContext context) { var timeoutCount = 0; var activityState = BuildActivityState(context); // If we have already re-tried 3 times, fail the workflow if (context.Markers.ContainsKey("ActivityTimeoutMarker")) { timeoutCount = Int32.Parse(context.Markers["ActivityTimeoutMarker"]); if (timeoutCount > 3) { return FailWorkflow("Failing workflow after 3 retry attempts.", "OnActivityTaskTimedOut"); } } // Bump the timeoutCount timeoutCount++; // Fetch the next step and set it up with the right input and increased timeout value var workflowStep = ((WorkflowActivitySetupContext) GetStep(true /* activity timed out */, false /* is timer */, context.ActivityName, context.ActivityVersion)).Clone(); switch (context.TimeoutType) { case "START_TO_CLOSE": workflowStep.StartToCloseTimeout = (Int32.Parse(workflowStep.StartToCloseTimeout) * timeoutCount).ToString(CultureInfo.InvariantCulture); break; case "SCHEDULE_TO_START": workflowStep.ScheduleToStartTimeout = (Int32.Parse(workflowStep.ScheduleToStartTimeout) * timeoutCount).ToString(CultureInfo.InvariantCulture); break; case "SCHEDULE_TO_CLOSE": workflowStep.ScheduleToCloseTimeout = (Int32.Parse(workflowStep.ScheduleToCloseTimeout) * timeoutCount).ToString(CultureInfo.InvariantCulture); break; case "HEARTBEAT": workflowStep.HeartbeatTimeout = (Int32.Parse(workflowStep.HeartbeatTimeout) * timeoutCount).ToString(CultureInfo.InvariantCulture); break; default: Debug.Assert(false, "Unknown timeout type " + context.TimeoutType); break; } if (string.IsNullOrEmpty(workflowStep.Input)) { workflowStep.Input = activityState; } // Fetch the decision to re-schedule the activity var request = ScheduleActivityTask(workflowStep); // Fetch the decision for a new timeout marker and add it to the schedule activity request var marker = RecordMarker(timeoutCount.ToString(CultureInfo.InvariantCulture), "ActivityTimeoutMarker"); request.Decisions.Add(marker.Decisions[0]); // Return the combined request return request; }
/// <summary> /// Set up a fail workflow decision in the event of an activity failing. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnActivityTaskFailed(WorkflowDecisionContext context) { return FailWorkflow(context.Details, context.Reason); }
/// <summary> /// Set up a fail workflow decision in the event of failure to start a child workflow. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnStartChildWorkflowExecutionFailed(WorkflowDecisionContext context) { return FailWorkflow(context.Cause, "OnStartChildWorkflowExecutionFailed"); }
/// <summary> /// Sets up a new activity or child workflow as specified by the workflow at the re-start of the workflow. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnWorkflowExecutionContinuedAsNew( WorkflowDecisionContext context) { return(OnWorkflowExecutionStarted(context)); }
/// <summary> /// Sets up a new activity or child workflow as specified by the workflow at the re-start of the workflow. /// </summary> /// <param name="context">Workflow decision context supplied by SimpleWorkflowFramework.NET.</param> /// <returns>Properly set up decision completed request.</returns> public virtual RespondDecisionTaskCompletedRequest OnWorkflowExecutionContinuedAsNew( WorkflowDecisionContext context) { return OnWorkflowExecutionStarted(context); }