public virtual void OnActivityExecuting(WorkflowContext workflowContext, ActivityContext activityContext, CancellationToken cancellationToken) { }
public virtual void OnWorkflowResuming(WorkflowContext context, CancellationToken cancellationToken) { }
private void ResumeWorkflow(AwaitingActivityRecord awaitingActivityRecord, WorkflowContext workflowContext, IDictionary<string, object> tokens) { // signal every activity that the workflow is about to be resumed var cancellationToken = new CancellationToken(); InvokeActivities(activity => activity.OnWorkflowResuming(workflowContext, cancellationToken)); if (cancellationToken.IsCancelled) { // workflow is aborted return; } // signal every activity that the workflow is resumed InvokeActivities(activity => activity.OnWorkflowResumed(workflowContext)); var workflow = awaitingActivityRecord.WorkflowRecord; workflowContext.Record = workflow; workflow.AwaitingActivities.Remove(awaitingActivityRecord); var blockedOn = ExecuteWorkflow(workflowContext, awaitingActivityRecord.ActivityRecord, tokens).ToList(); // is the workflow halted on a blocking activity, and there is no more awaiting activities if (!blockedOn.Any() && !workflow.AwaitingActivities.Any()) { // no, delete the workflow _workflowRepository.Delete(awaitingActivityRecord.WorkflowRecord); } else { // add the new ones foreach (var blocking in blockedOn) { workflow.AwaitingActivities.Add(new AwaitingActivityRecord { ActivityRecord = blocking, WorkflowRecord = workflow }); } } }
public IEnumerable<ActivityRecord> ExecuteWorkflow(WorkflowContext workflowContext, ActivityRecord activityRecord, IDictionary<string, object> tokens) { var firstPass = true; var scheduled = new Stack<ActivityRecord>(); scheduled.Push(activityRecord); var blocking = new List<ActivityRecord>(); while (scheduled.Any()) { activityRecord = scheduled.Pop(); var activityContext = CreateActivityContext(activityRecord, tokens); // while there is an activity to process if (!firstPass){ if (activityContext.Activity.IsEvent) { blocking.Add(activityRecord); continue; } } else { firstPass = false; } // signal every activity that the activity is about to be executed var cancellationToken = new CancellationToken(); InvokeActivities(activity => activity.OnActivityExecuting(workflowContext, activityContext, cancellationToken)); if (cancellationToken.IsCancelled) { // activity is aborted continue; } var outcomes = activityContext.Activity.Execute(workflowContext, activityContext).ToList(); // signal every activity that the activity is executed InvokeActivities(activity => activity.OnActivityExecuted(workflowContext, activityContext)); foreach (var outcome in outcomes) { // look for next activity in the graph var transition = workflowContext.Record.WorkflowDefinitionRecord.TransitionRecords.FirstOrDefault(x => x.SourceActivityRecord == activityRecord && x.SourceEndpoint == outcome.TextHint); if (transition != null) { scheduled.Push(transition.DestinationActivityRecord); } } } // apply Distinct() as two paths could block on the same activity return blocking.Distinct(); }
private void StartWorkflow(WorkflowContext workflowContext, ActivityRecord activityRecord, IDictionary<string, object> tokens) { // signal every activity that the workflow is about to start var cancellationToken = new CancellationToken(); InvokeActivities(activity => activity.OnWorkflowStarting(workflowContext, cancellationToken)); if (cancellationToken.IsCancelled) { // workflow is aborted return; } // signal every activity that the workflow is has started InvokeActivities(activity => activity.OnWorkflowStarted(workflowContext)); var blockedOn = ExecuteWorkflow(workflowContext, activityRecord, tokens).ToList(); // is the workflow halted on a blocking activity ? if (!blockedOn.Any()) { // no, nothing to do } else { // workflow halted, create a workflow state _workflowRepository.Create(workflowContext.Record); foreach (var blocking in blockedOn) { workflowContext.Record.AwaitingActivities.Add(new AwaitingActivityRecord { ActivityRecord = blocking, WorkflowRecord = workflowContext.Record }); } } }