Example #1
0
 public override async ValueTask <WorkflowState> LoadAsync(
     LoadWorkflowContext context,
     CancellationToken cancellationToken = default) =>
 await this.session.Query <WorkflowState, WorkflowStateIndex>(x => x.StateId == context.ContextId).FirstOrDefaultAsync();
Example #2
0
 public async ValueTask <object?> LoadAsync(LoadWorkflowContext context, CancellationToken cancellationToken = default)
 {
     return(await _repository.GetAsync(context.ContextId));
 }
        protected virtual async Task <RunWorkflowResult> RunWorkflowInternalAsync(WorkflowExecutionContext workflowExecutionContext, string?activityId = default, CancellationToken cancellationToken = default)
        {
            var workflowInstance = workflowExecutionContext.WorkflowInstance;

            if (!string.IsNullOrWhiteSpace(workflowInstance.ContextId))
            {
                var loadContext = new LoadWorkflowContext(workflowExecutionContext);
                workflowExecutionContext.WorkflowContext = await _workflowContextManager.LoadContext(loadContext, cancellationToken);
            }

            // If the workflow instance has a CurrentActivity, it means the workflow instance is being retried.
            var currentActivity = workflowInstance.CurrentActivity;

            if (activityId == null && currentActivity != null)
            {
                activityId = currentActivity.ActivityId;
            }

            var workflowBlueprint = workflowExecutionContext.WorkflowBlueprint;
            var activity          = activityId != null?workflowBlueprint.GetActivity(activityId) : default;

            // Give application a chance to prevent workflow from executing.
            var validateWorkflowExecution = new ValidateWorkflowExecution(workflowExecutionContext, activity);
            await _mediator.Publish(validateWorkflowExecution, cancellationToken);

            if (!validateWorkflowExecution.CanExecuteWorkflow)
            {
                _logger.LogInformation("Workflow execution prevented for workflow {WorkflowInstanceId}", workflowInstance.Id);
                return(new RunWorkflowResult(workflowInstance, activityId, null, false));
            }

            await _mediator.Publish(new WorkflowExecuting(workflowExecutionContext), cancellationToken);

            RunWorkflowResult runWorkflowResult;

            switch (workflowExecutionContext.Status)
            {
            case WorkflowStatus.Idle:
                runWorkflowResult = await BeginWorkflow(workflowExecutionContext, activity, cancellationToken);

                if (!runWorkflowResult.Executed)
                {
                    if (workflowInstance.WorkflowStatus != WorkflowStatus.Faulted)
                    {
                        _logger.LogDebug("Workflow {WorkflowInstanceId} cannot begin from an idle state (perhaps it needs a specific input)", workflowInstance.Id);
                        return(runWorkflowResult);
                    }
                }

                break;

            case WorkflowStatus.Running:
                runWorkflowResult = await RunWorkflowAsync(workflowExecutionContext, activity, cancellationToken);

                break;

            case WorkflowStatus.Suspended:
                runWorkflowResult = await ResumeWorkflowAsync(workflowExecutionContext, activity !, cancellationToken);

                if (!runWorkflowResult.Executed)
                {
                    _logger.LogDebug("Workflow {WorkflowInstanceId} cannot be resumed from a suspended state (perhaps it needs a specific input)", workflowInstance.Id);
                    return(runWorkflowResult);
                }

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            await _mediator.Publish(new WorkflowExecuted(workflowExecutionContext), cancellationToken);

            var statusEvents = workflowExecutionContext.Status switch
            {
                WorkflowStatus.Cancelled => new INotification[] { new WorkflowCancelled(workflowExecutionContext), new WorkflowInstanceCancelled(workflowInstance) },
                WorkflowStatus.Finished => new INotification[] { new WorkflowCompleted(workflowExecutionContext) },
                WorkflowStatus.Faulted => new INotification[] { new WorkflowFaulted(workflowExecutionContext) },
                WorkflowStatus.Suspended => new INotification[] { new WorkflowSuspended(workflowExecutionContext) },
                _ => Array.Empty <INotification>()
            };

            foreach (var statusEvent in statusEvents)
            {
                await _mediator.Publish(statusEvent, cancellationToken);
            }

            await _mediator.Publish(new WorkflowExecutionFinished(workflowExecutionContext), cancellationToken);

            return(runWorkflowResult);
        }
 async ValueTask <object?> ILoadWorkflowContext.LoadAsync(LoadWorkflowContext context, CancellationToken cancellationToken) => await LoadAsync(context, cancellationToken);