public async Task <WorkflowExecutionContext> ResumeWorkflowAsync(Workflow workflow,
                                                                         BlockingActivity awaitingActivity, IDictionary <string, object> input = null)
        {
            var workflowType = await _workflowTypeStore.GetAsync(workflow.WorkflowTypeId);

            var activityRecord =
                workflowType.Activities.SingleOrDefault(x => x.ActivityId == awaitingActivity.ActivityId);
            var workflowContext = await CreateWorkflowExecutionContextAsync(workflowType, workflow, input);

            workflowContext.Status = WorkflowStatus.Resuming;

            // Signal every activity that the workflow is about to be resumed.
            var cancellationToken = new CancellationToken();

            await InvokeActivitiesAsync(workflowContext, x => x.Activity.OnInputReceivedAsync(workflowContext, input));
            await InvokeActivitiesAsync(workflowContext,
                                        x => x.Activity.OnWorkflowResumingAsync(workflowContext, cancellationToken));

            if (cancellationToken.IsCancellationRequested)
            {
                // Workflow is aborted.
                workflowContext.Status = WorkflowStatus.Aborted;
            }
            else
            {
                // Check if the current activity can execute.
                if (activityRecord != null)
                {
                    var activityContext = workflowContext.GetActivity(activityRecord.ActivityId);
                    if (await activityContext.Activity.CanExecuteAsync(workflowContext, activityContext))
                    {
                        // Signal every activity that the workflow is resumed.
                        await InvokeActivitiesAsync(workflowContext,
                                                    x => x.Activity.OnWorkflowResumedAsync(workflowContext));

                        // Remove the blocking activity.
                        workflowContext.Workflow.BlockingActivities.Remove(awaitingActivity);

                        // Resume the workflow at the specified blocking activity.
                        await ExecuteWorkflowAsync(workflowContext, activityRecord);
                    }
                    else
                    {
                        workflowContext.Status = WorkflowStatus.Halted;
                        return(workflowContext);
                    }
                }
            }

            if (workflowContext.Status == WorkflowStatus.Finished && workflowType.DeleteFinishedWorkflows)
            {
                await _workflowStore.DeleteAsync(workflowContext.Workflow);
            }
            else
            {
                await PersistAsync(workflowContext);
            }

            return(workflowContext);
        }
示例#2
0
        protected override void Execute(ActivityExecutionContext activityExecutionContext)
        {
            var activityDefinition = activityExecutionContext.ActivityBlueprint;
            var blockingActivity   = new BlockingActivity(activityDefinition.Id, activityDefinition.Type);

            activityExecutionContext.WorkflowExecutionContext.WorkflowInstance.BlockingActivities.Add(blockingActivity);
            activityExecutionContext.WorkflowExecutionContext.Suspend();
        }
示例#3
0
        public override async ValueTask ExecuteAsync(ActivityExecutionContext activityExecutionContext, CancellationToken cancellationToken)
        {
            var activityDefinition = activityExecutionContext.ActivityBlueprint;
            var blockingActivity   = new BlockingActivity(activityDefinition.Id, activityDefinition.Type);

            activityExecutionContext.WorkflowExecutionContext.WorkflowInstance.BlockingActivities.Add(blockingActivity);
            activityExecutionContext.WorkflowExecutionContext.Suspend();

            var mediator = activityExecutionContext.ServiceProvider.GetRequiredService <IMediator>();
            await mediator.Publish(new BlockingActivityAdded(activityExecutionContext.WorkflowExecutionContext, blockingActivity), cancellationToken);
        }
示例#4
0
        public async Task <IEnumerable <ActivityRecord> > ExecuteWorkflowAsync(WorkflowExecutionContext workflowContext, ActivityRecord activity)
        {
            var workflowType = workflowContext.WorkflowType;
            var scheduled    = new Stack <ActivityRecord>();
            var blocking     = new List <ActivityRecord>();
            var isResuming   = workflowContext.Status == WorkflowStatus.Resuming;
            var isFirstPass  = true;

            workflowContext.Status = WorkflowStatus.Executing;
            scheduled.Push(activity);

            while (scheduled.Count > 0)
            {
                activity = scheduled.Pop();

                var activityContext = workflowContext.GetActivity(activity.ActivityId);

                // Signal every activity that the activity is about to be executed.
                var cancellationToken = new CancellationToken();
                await InvokeActivitiesAsync(workflowContext, x => x.Activity.OnActivityExecutingAsync(workflowContext, activityContext, cancellationToken));

                if (cancellationToken.IsCancellationRequested)
                {
                    // Activity is aborted.
                    workflowContext.Status = WorkflowStatus.Aborted;
                    break;
                }

                IList <string> outcomes = new List <string>(0);

                try
                {
                    ActivityExecutionResult result;

                    if (!isResuming)
                    {
                        // Execute the current activity.
                        result = await activityContext.Activity.ExecuteAsync(workflowContext, activityContext);
                    }
                    else
                    {
                        // Resume the current activity.
                        result = await activityContext.Activity.ResumeAsync(workflowContext, activityContext);

                        isResuming = false;
                    }

                    if (result.IsHalted)
                    {
                        if (isFirstPass)
                        {
                            // Resume immediately when this is the first pass.
                            result = await activityContext.Activity.ResumeAsync(workflowContext, activityContext);

                            isFirstPass = false;
                            outcomes    = result.Outcomes;

                            if (result.IsHalted)
                            {
                                // Block on this activity.
                                blocking.Add(activity);
                            }
                        }
                        else
                        {
                            // Block on this activity.
                            blocking.Add(activity);

                            continue;
                        }
                    }
                    else
                    {
                        outcomes = result.Outcomes;
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "An unhandled error occurred while executing an activity. Workflow ID: '{WorkflowTypeId}'. Activity: '{ActivityId}', '{ActivityName}'. Putting the workflow in the faulted state.", workflowType.Id, activityContext.ActivityRecord.ActivityId, activityContext.ActivityRecord.Name);
                    workflowContext.Fault(ex, activityContext);
                    return(blocking.Distinct());
                }

                // Signal every activity that the activity is executed.
                await InvokeActivitiesAsync(workflowContext, x => x.Activity.OnActivityExecutedAsync(workflowContext, activityContext));

                foreach (var outcome in outcomes)
                {
                    // Look for next activity in the graph.
                    var transition = workflowType.Transitions.FirstOrDefault(x => x.SourceActivityId == activity.ActivityId && x.SourceOutcomeName == outcome);

                    if (transition != null)
                    {
                        var destinationActivity = workflowContext.WorkflowType.Activities.SingleOrDefault(x => x.ActivityId == transition.DestinationActivityId);
                        scheduled.Push(destinationActivity);
                    }
                }

                isFirstPass = false;
            }

            // Apply Distinct() as two paths could block on the same activity.
            var blockingActivities = blocking.Distinct().ToList();

            workflowContext.Status = blockingActivities.Any() || workflowContext.Workflow.BlockingActivities.Any() ? WorkflowStatus.Halted : WorkflowStatus.Finished;

            foreach (var blockingActivity in blockingActivities)
            {
                // Workflows containing event activities could end up being blocked on the same activity.
                if (!workflowContext.Workflow.BlockingActivities.Any(x => x.ActivityId == blockingActivity.ActivityId))
                {
                    workflowContext.Workflow.BlockingActivities.Add(BlockingActivity.FromActivity(blockingActivity));
                }
            }

            return(blockingActivities);
        }
示例#5
0
 public BlockingActivityRemoved(WorkflowExecutionContext workflowExecutionContext, BlockingActivity blockingActivity)
 {
     WorkflowExecutionContext = workflowExecutionContext;
     BlockingActivity         = blockingActivity;
 }