public async Task <WorkflowExecutionContext> InvokeAsync(Workflow workflow, IActivity startActivity = default, Variables arguments = default, CancellationToken cancellationToken = default) { workflow.Arguments = arguments ?? new Variables(); var workflowExecutionContext = new WorkflowExecutionContext(workflow); var isResuming = workflowExecutionContext.Workflow.Status == WorkflowStatus.Resuming; if (startActivity != null) { workflow.BlockingActivities.Remove(startActivity); } else { startActivity = workflow.Activities.First(); } workflowExecutionContext.Workflow.Status = WorkflowStatus.Executing; workflowExecutionContext.ScheduleActivity(startActivity); while (workflowExecutionContext.HasScheduledActivities) { var currentActivity = workflowExecutionContext.PopScheduledActivity(); var result = await ExecuteActivityAsync(workflowExecutionContext, currentActivity, isResuming, cancellationToken); if (result == null) { break; } await result.ExecuteAsync(this, workflowExecutionContext, cancellationToken); workflowExecutionContext.IsFirstPass = false; isResuming = false; } if (workflowExecutionContext.Workflow.Status != WorkflowStatus.Halted) { workflowExecutionContext.Finish(); } return(workflowExecutionContext); }
private async ValueTask RunCoreAsync(WorkflowExecutionContext workflowExecutionContext, ActivityOperation activityOperation, CancellationToken cancellationToken = default) { var scope = workflowExecutionContext.ServiceProvider; var workflowBlueprint = workflowExecutionContext.WorkflowBlueprint; var workflowInstance = workflowExecutionContext.WorkflowInstance; var burstStarted = false; while (workflowExecutionContext.HasScheduledActivities) { var scheduledActivity = workflowInstance.CurrentActivity = workflowExecutionContext.PopScheduledActivity(); var currentActivityId = scheduledActivity.ActivityId; var activityBlueprint = workflowBlueprint.GetActivity(currentActivityId) !; var resuming = activityOperation == Resume; var outputReference = workflowInstance.Output; var output = outputReference != null ? await _workflowStorageService.LoadAsync(outputReference.ProviderName, new WorkflowStorageContext(workflowInstance, outputReference.ActivityId), "Output", cancellationToken) : null; var input = !burstStarted ? workflowExecutionContext.Input : scheduledActivity.Input ?? output; var activityExecutionContext = new ActivityExecutionContext(scope, workflowExecutionContext, activityBlueprint, input, resuming, cancellationToken); var runtimeActivityInstance = await activityExecutionContext.ActivateActivityAsync(cancellationToken); var activityType = runtimeActivityInstance.ActivityType; using var executionScope = AmbientActivityExecutionContext.EnterScope(activityExecutionContext); var activity = await activityType.ActivateAsync(activityExecutionContext); if (!burstStarted) { await _mediator.Publish(new WorkflowExecutionBurstStarting(workflowExecutionContext, activityExecutionContext), cancellationToken); burstStarted = true; } if (resuming) { await _mediator.Publish(new ActivityResuming(activityExecutionContext, activity), cancellationToken); } await _mediator.Publish(new ActivityExecuting(activityExecutionContext, activity), cancellationToken); var result = await TryExecuteActivityAsync(activityOperation, activityExecutionContext, activity, cancellationToken); if (result == null) { return; } await _mediator.Publish(new ActivityExecuted(activityExecutionContext, activity), cancellationToken); await _mediator.Publish(new ActivityExecutionResultExecuting(result, activityExecutionContext), cancellationToken); await result.ExecuteAsync(activityExecutionContext, cancellationToken); workflowExecutionContext.CompletePass(); workflowInstance.LastExecutedActivityId = currentActivityId; await _mediator.Publish(new ActivityExecutionResultExecuted(result, activityExecutionContext), cancellationToken); await _mediator.Publish(new WorkflowExecutionPassCompleted(workflowExecutionContext, activityExecutionContext), cancellationToken); if (!workflowExecutionContext.HasScheduledActivities) { await _mediator.Publish(new WorkflowExecutionBurstCompleted(workflowExecutionContext, activityExecutionContext), cancellationToken); } activityOperation = Execute; } workflowInstance.CurrentActivity = null; if (workflowExecutionContext.HasBlockingActivities) { workflowExecutionContext.Suspend(); } if (workflowExecutionContext.Status == WorkflowStatus.Running) { await workflowExecutionContext.CompleteAsync(); } }
public async Task <WorkflowExecutionContext> InvokeAsync(Workflow workflow, IActivity startActivity = default, Variables arguments = default, CancellationToken cancellationToken = default) { workflow.Arguments = arguments ?? new Variables(); var workflowExecutionContext = new WorkflowExecutionContext(workflow); var isResuming = workflowExecutionContext.Workflow.Status == WorkflowStatus.Resuming; // If a start activity was provided, remove it from the blocking activities list. If not start activity was provided, pick the first one that has no inbound connections. if (startActivity != null) { workflow.BlockingActivities.Remove(startActivity); } else { startActivity = workflow.GetStartActivities().FirstOrDefault(); } if (!isResuming) { workflow.StartedAt = clock.GetCurrentInstant(); } workflowExecutionContext.Workflow.Status = WorkflowStatus.Executing; if (startActivity != null) { workflowExecutionContext.ScheduleActivity(startActivity); } // Keep executing activities as long as there are any scheduled. while (workflowExecutionContext.HasScheduledActivities) { var currentActivity = workflowExecutionContext.PopScheduledActivity(); var result = await ExecuteActivityAsync(workflowExecutionContext, currentActivity, isResuming, cancellationToken); if (result == null) { break; } await result.ExecuteAsync(this, workflowExecutionContext, cancellationToken); workflowExecutionContext.IsFirstPass = false; isResuming = false; } // Any other status than Halted means the workflow has ended (either because it reached the final activity, was aborted or has faulted). if (workflowExecutionContext.Workflow.Status != WorkflowStatus.Halted) { workflowExecutionContext.Finish(clock.GetCurrentInstant()); } else { // Persist workflow before executing the halted activities. await workflowStore.SaveAsync(workflow, cancellationToken); // Invoke Halted event on activity drivers that halted the workflow. while (workflowExecutionContext.HasScheduledHaltingActivities) { var currentActivity = workflowExecutionContext.PopScheduledHaltingActivity(); var result = await ExecuteActivityHaltedAsync(workflowExecutionContext, currentActivity, cancellationToken); await result.ExecuteAsync(this, workflowExecutionContext, cancellationToken); } } await workflowStore.SaveAsync(workflow, cancellationToken); return(workflowExecutionContext); }