public static async ValueTask <object?> EvaluateActivityPropertyValue( this IWorkflowBlueprint workflowBlueprint, string activityId, string propertyName, ActivityExecutionContext activityExecutionContext, CancellationToken cancellationToken) { var provider = workflowBlueprint.ActivityPropertyProviders.GetProvider(activityId, propertyName); var value = provider != null ? await provider.GetValueAsync(activityExecutionContext, cancellationToken) : null; if (value == null) { // Get default value. var activityTypeService = activityExecutionContext.GetService <IActivityTypeService>(); var activityBlueprint = workflowBlueprint.GetActivity(activityId) !; var activityType = await activityTypeService.GetActivityTypeAsync(activityBlueprint.Type, cancellationToken); var activityDescriptor = await activityTypeService.DescribeActivityType(activityType, cancellationToken); var propertyDescriptor = activityDescriptor.InputProperties.FirstOrDefault(x => x.Name == propertyName); value = propertyDescriptor?.DefaultValue; } return(value); }
public virtual async Task <RunWorkflowResult> RunWorkflowAsync( IWorkflowBlueprint workflowBlueprint, WorkflowInstance workflowInstance, string?activityId = default, object?input = default, CancellationToken cancellationToken = default) { using var loggingScope = _logger.BeginScope(new Dictionary <string, object> { ["WorkflowInstanceId"] = workflowInstance.Id }); using var workflowExecutionScope = _serviceScopeFactory.CreateScope(); var workflowExecutionContext = new WorkflowExecutionContext(workflowExecutionScope.ServiceProvider, workflowBlueprint, workflowInstance, input); 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 (currentActivity != null) { activityId = currentActivity.ActivityId; } 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, 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) { _logger.LogDebug("Workflow {WorkflowInstanceId} cannot begin from an idle state (perhaps it needs a specific input)", workflowInstance.Id); return(runWorkflowResult); } break; case WorkflowStatus.Running: await RunWorkflowAsync(workflowExecutionContext, cancellationToken); runWorkflowResult = new RunWorkflowResult(workflowInstance, activityId, true); 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 statusEvent = workflowExecutionContext.Status switch { WorkflowStatus.Cancelled => new WorkflowCancelled(workflowExecutionContext), WorkflowStatus.Finished => new WorkflowCompleted(workflowExecutionContext), WorkflowStatus.Faulted => new WorkflowFaulted(workflowExecutionContext), WorkflowStatus.Suspended => new WorkflowSuspended(workflowExecutionContext), _ => default(INotification) }; if (statusEvent != null) { _logger.LogTrace("Publishing a status event of type {EventType} for workflow {WorkflowInstanceId}", statusEvent.GetType().Name, workflowInstance.Id); await _mediator.Publish(statusEvent, cancellationToken); } await _mediator.Publish(new WorkflowExecutionFinished(workflowExecutionContext), cancellationToken); return(runWorkflowResult); }