public async Task DispatchAsync(ExecuteWorkflowInstanceRequest request, CancellationToken cancellationToken = default) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(request.WorkflowInstanceId, cancellationToken); if (workflowInstance == null) { _logger.LogWarning("Cannot dispatch a workflow instance ID that does not exist"); return; } var workflowBlueprint = await _workflowRegistry.FindAsync(workflowInstance.DefinitionId, VersionOptions.SpecificVersion(workflowInstance.Version), workflowInstance.TenantId, cancellationToken); if (workflowBlueprint == null) { _logger.LogWarning("Workflow instance {WorkflowInstanceId} references workflow blueprint {WorkflowDefinitionId} with version {Version}, but could not be found", workflowInstance.Id, workflowInstance.DefinitionId, workflowInstance.Version); return; } var channel = _workflowChannelOptions.GetChannelOrDefault(workflowBlueprint.Channel); var queue = ServiceBusOptions.FormatChannelQueueName <ExecuteWorkflowInstanceRequest>(channel); await _commandSender.SendAsync(request, queue, cancellationToken : cancellationToken); }
public async Task <CancelWorkflowInstanceResult> CancelAsync(string workflowInstanceId, CancellationToken cancellationToken = default) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(workflowInstanceId, cancellationToken); if (workflowInstance == null) { return(new CancelWorkflowInstanceResult(CancelWorkflowInstanceResultStatus.NotFound, null)); } if (workflowInstance.WorkflowStatus != WorkflowStatus.Idle && workflowInstance.WorkflowStatus != WorkflowStatus.Running && workflowInstance.WorkflowStatus != WorkflowStatus.Suspended) { return(new CancelWorkflowInstanceResult(CancelWorkflowInstanceResultStatus.InvalidStatus, workflowInstance)); } workflowInstance.BlockingActivities = new HashSet <BlockingActivity>(); workflowInstance.CurrentActivity = null; workflowInstance.WorkflowStatus = WorkflowStatus.Cancelled; workflowInstance.CancelledAt = _clock.GetCurrentInstant(); await _workflowInstanceStore.SaveAsync(workflowInstance, cancellationToken); await _mediator.Publish(new WorkflowInstanceCancelled(workflowInstance), cancellationToken); return(new CancelWorkflowInstanceResult(CancelWorkflowInstanceResultStatus.Ok, workflowInstance)); }
public async Task StartAsync(CancellationToken cancellationToken) { var instance = await _workflowRunner.BuildAndStartWorkflowAsync <PersistableWorkflow>(cancellationToken : cancellationToken); var retrievedInstance = await _instanceStore.FindByIdAsync(instance.Id, cancellationToken); Assert.NotNull(retrievedInstance); }
protected override async ValueTask <IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context) { var workflowInstance = await _workflowInstanceManager.FindByIdAsync(WorkflowInstanceId, context.CancellationToken); await _workflowTriggerInterruptor.InterruptActivityAsync(workflowInstance !, BlockingActivityId, Input, context.CancellationToken); return(Done()); }
public async Task <RunWorkflowResult> ExecuteAsync(string workflowInstanceId, string?activityId, WorkflowInput?input = default, CancellationToken cancellationToken = default) { var workflowInstanceLockKey = $"workflow-instance:{workflowInstanceId}"; var currentWorkflowInstanceLockHandle = AmbientLockContext.GetCurrentWorkflowInstanceLock(workflowInstanceId); var workflowInstanceLockHandle = currentWorkflowInstanceLockHandle ?? await _distributedLockProvider.AcquireLockAsync(workflowInstanceLockKey, _elsaOptions.DistributedLockTimeout, cancellationToken); if (workflowInstanceLockHandle == null) { throw new LockAcquisitionException("Could not acquire a lock within the configured amount of time"); } try { AmbientLockContext.SetCurrentWorkflowInstanceLock(workflowInstanceId, workflowInstanceLockHandle); var workflowInstance = await _workflowInstanceStore.FindByIdAsync(workflowInstanceId, cancellationToken); if (workflowInstance == null) { _logger.LogWarning("Could not run workflow instance with ID {WorkflowInstanceId} because it does not exist", workflowInstanceId); return(new RunWorkflowResult(workflowInstance, activityId, false)); } var correlationId = workflowInstance.CorrelationId; if (!string.IsNullOrWhiteSpace(correlationId)) { // We need to lock on correlation ID to prevent a race condition with WorkflowLaunchpad that is used to find workflows by correlation ID to execute. // The race condition is: when a workflow instance is done executing, the BookmarkIndexer will collect bookmarks. // But if in the meantime an event comes in that triggers correlated workflows, the bookmarks may not have been created yet. var currentCorrelationLockHandle = AmbientLockContext.CurrentCorrelationLock; var correlationLockHandle = currentCorrelationLockHandle ?? await _distributedLockProvider.AcquireLockAsync(correlationId, _elsaOptions.DistributedLockTimeout, cancellationToken); if (correlationLockHandle == null) { throw new LockAcquisitionException($"Could not acquire a lock on correlation {correlationId} within the configured amount of time"); } try { AmbientLockContext.CurrentCorrelationLock = correlationLockHandle; return(await _workflowInstanceExecutor.ExecuteAsync(workflowInstance, activityId, input, cancellationToken)); } finally { AmbientLockContext.CurrentCorrelationLock = null; await correlationLockHandle.DisposeAsync(); } } return(await _workflowInstanceExecutor.ExecuteAsync(workflowInstance, activityId, input, cancellationToken)); } finally { AmbientLockContext.DeleteCurrentWorkflowInstanceLock(workflowInstanceId); await workflowInstanceLockHandle.DisposeAsync(); } }
public async Task Handle(WorkflowTestExecutionStopped notification, CancellationToken cancellationToken) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(notification.WorkflowInstanceId, cancellationToken); if (workflowInstance != null) { await _bookmarkIndexer.IndexBookmarksAsync(workflowInstance, cancellationToken); } }
public async Task <RunWorkflowResult> ExecuteAsync(string workflowInstanceId, string?activityId, object?input = default, CancellationToken cancellationToken = default) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(workflowInstanceId, cancellationToken); if (!ValidatePreconditions(workflowInstanceId, workflowInstance, activityId)) { return(new RunWorkflowResult(workflowInstance, activityId, false)); } return(await ExecuteAsync(workflowInstance !, activityId, input, cancellationToken)); }
public async Task StartAsync(CancellationToken cancellationToken) { var instance = await _workflowRunner.BuildAndStartWorkflowAsync <TWorkflow>(cancellationToken : cancellationToken); var retrievedInstance = await _instanceStore.FindByIdAsync(instance.Id, cancellationToken); // An instance should totally be retrieved from the store Assert.NotNull(retrievedInstance); // Because we are in-memory, it should be a reference to the same instance Assert.Same(instance, retrievedInstance); }
public async Task ResumeWorkflowsAsync(IEnumerable <BookmarkFinderResult> results, object?input = default, string?correlationId = default, string?contextId = default, CancellationToken cancellationToken = default) { foreach (var result in results) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(result.WorkflowInstanceId, cancellationToken); if (workflowInstance?.WorkflowStatus == WorkflowStatus.Suspended) { await ResumeWorkflowAsync(workflowInstance !, result.ActivityId, input, cancellationToken); } } }
public async Task <DeleteWorkflowInstanceResult> DeleteAsync(string workflowInstanceId, CancellationToken cancellationToken = default) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(workflowInstanceId, cancellationToken); if (workflowInstance == null) { return(new DeleteWorkflowInstanceResult(DeleteWorkflowInstanceResultStatus.NotFound, null)); } await _workflowInstanceStore.DeleteAsync(workflowInstance, cancellationToken); return(new DeleteWorkflowInstanceResult(DeleteWorkflowInstanceResultStatus.Ok, workflowInstance)); }
public async Task <IActionResult> Handle(string id, CancellationToken cancellationToken = default) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(id, cancellationToken); if (workflowInstance == null) { return(NotFound()); } await _workflowInstanceStore.DeleteAsync(workflowInstance, cancellationToken); return(NoContent()); }
public async Task ResumeWorkflowsAsync(IEnumerable <BookmarkFinderResult> results, WorkflowInput?input = default, CancellationToken cancellationToken = default) { foreach (var result in results) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(result.WorkflowInstanceId, cancellationToken); if (workflowInstance?.WorkflowStatus == WorkflowStatus.Suspended) { await _workflowStorageService.UpdateInputAsync(workflowInstance, input, cancellationToken); await ResumeWorkflowAsync(workflowInstance !, result.ActivityId, cancellationToken); } } }
public async Task <Unit> Handle(ExecuteWorkflowInstanceRequest request, CancellationToken cancellationToken) { var workflowInstanceId = request.WorkflowInstanceId; var workflowInstance = await _workflowInstanceStore.FindByIdAsync(request.WorkflowInstanceId, cancellationToken); if (!ValidatePreconditions(workflowInstanceId, workflowInstance, request.ActivityId)) { return(Unit.Value); } await _workflowRunner.ResumeWorkflowAsync( workflowInstance !, request.ActivityId, request.Input, cancellationToken); return(Unit.Value); }
public async Task <IActionResult> Handle(string id, CancellationToken cancellationToken = default) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(id, cancellationToken); if (workflowInstance == null) { return(NotFound()); } var tenantId = await _tenantAccessor.GetTenantIdAsync(cancellationToken); var workflowBlueprint = await _workflowRegistry.FindByDefinitionVersionIdAsync(workflowInstance.DefinitionVersionId, tenantId, cancellationToken); await _publisher.Publish(new RequestingWorkflowInstance(workflowInstance, workflowBlueprint !), cancellationToken); return(Json(workflowInstance, _contentSerializer.GetSettings())); }
protected override async ValueTask <IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context) { var cancellationToken = context.CancellationToken; var workflowInstance = await _workflowInstanceManager.FindByIdAsync(WorkflowInstanceId, cancellationToken); if (workflowInstance == null) { throw new WorkflowException($"Could not find workflow instance by ID {WorkflowInstanceId}"); } if (Input != null) { workflowInstance.Input = await _workflowStorageService.SaveAsync(new WorkflowInput(Input), workflowInstance, cancellationToken); } await _workflowTriggerInterruptor.InterruptActivityAsync(workflowInstance !, BlockingActivityId, cancellationToken); return(Done()); }
public async Task <IActionResult> Handle(string id, RetryWorkflowRequest?options, CancellationToken cancellationToken = default) { var workflowInstance = await _store.FindByIdAsync(id, cancellationToken); if (workflowInstance == null) { return(NotFound()); } if (options?.RunImmediately == false) { workflowInstance = await _reviver.ReviveAndQueueAsync(workflowInstance, cancellationToken); var model = new { WorkflowInstanceId = workflowInstance.Id, }; return(Accepted(model)); } var runWorkflowResult = await _reviver.ReviveAndRunAsync(workflowInstance, cancellationToken); workflowInstance = runWorkflowResult.WorkflowInstance !; if (workflowInstance.WorkflowStatus == WorkflowStatus.Faulted) { return(StatusCode(500, new { WorkflowInstanceId = workflowInstance.Id, Fault = workflowInstance.Fault }).ConfigureForEndpoint()); } return(Response.HasStarted ? new EmptyResult() : Json(new { WorkflowInstanceId = workflowInstance.Id, WorkflowStatus = workflowInstance.WorkflowStatus }, _serializerSettingsProvider.GetSettings())); }
public async Task <IActionResult> Handle(string id, RetryWorkflowRequest?options, CancellationToken cancellationToken = default) { var workflowInstance = await _store.FindByIdAsync(id, cancellationToken); if (workflowInstance == null) { return(NotFound()); } if (options?.RunImmediately == false) { workflowInstance = await _reviver.ReviveAndQueueAsync(workflowInstance, cancellationToken); var model = new { WorkflowInstanceId = workflowInstance.Id, }; return(Accepted(model)); } workflowInstance = await _reviver.ReviveAndRunAsync(workflowInstance, cancellationToken); if (workflowInstance.WorkflowStatus == WorkflowStatus.Faulted) { return(StatusCode(500, new { WorkflowInstanceId = workflowInstance.Id, Fault = workflowInstance.Fault })); } return(Response.HasStarted ? (IActionResult) new EmptyResult() : Ok(new { WorkflowInstanceId = workflowInstance.Id, WorkflowStatus = workflowInstance.WorkflowStatus })); }
public async Task <ActionResult <WorkflowInstance> > Handle(string id, CancellationToken cancellationToken = default) { var workflowInstance = await _workflowInstanceStore.FindByIdAsync(id, cancellationToken); return(workflowInstance ?? (ActionResult <WorkflowInstance>)NotFound()); }