Ejemplo n.º 1
0
        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.GetAsync(workflowInstance.DefinitionId, workflowInstance.TenantId, VersionOptions.SpecificVersion(workflowInstance.Version), 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);
        }
Ejemplo n.º 2
0
        public async Task <StartableWorkflow?> CollectStartableWorkflowAsync(string workflowDefinitionId, string?activityId, string?correlationId = default, string?contextId = default, string?tenantId = default, CancellationToken cancellationToken = default)
        {
            var workflowBlueprint = await _workflowRegistry.GetAsync(workflowDefinitionId, tenantId, VersionOptions.Published, cancellationToken);

            if (workflowBlueprint == null)
            {
                return(null);
            }

            return(await CollectStartableWorkflowAsync(workflowBlueprint, activityId, correlationId, contextId, tenantId, cancellationToken));
        }
        public async Task DispatchAsync(ExecuteWorkflowDefinitionRequest request, CancellationToken cancellationToken = default)
        {
            var workflowBlueprint = await _workflowRegistry.GetAsync(request.WorkflowDefinitionId, request.TenantId, VersionOptions.Published, cancellationToken);

            if (workflowBlueprint == null)
            {
                _logger.LogWarning("No published version found for workflow blueprint {WorkflowDefinitionId}", request.WorkflowDefinitionId);
                return;
            }

            var channel = _workflowChannelOptions.GetChannelOrDefault(workflowBlueprint.Channel);
            var queue   = ElsaOptions.FormatChannelQueueName <ExecuteWorkflowDefinitionRequest>(channel);

            EnqueueJob <WorkflowDefinitionJob>(x => x.ExecuteAsync(request, CancellationToken.None), queue);
        }
Ejemplo n.º 4
0
        public async Task <Unit> Handle(ExecuteWorkflowDefinitionRequest request, CancellationToken cancellationToken)
        {
            var workflowDefinitionId = request.WorkflowDefinitionId;
            var tenantId             = request.TenantId;
            var workflowBlueprint    = await _workflowRegistry.GetAsync(workflowDefinitionId, tenantId, VersionOptions.Published, cancellationToken);

            if (!ValidatePreconditions(workflowDefinitionId, workflowBlueprint))
            {
                return(Unit.Value);
            }

            var lockKey               = $"execute-workflow-definition:tenant:{tenantId}:workflow-definition:{workflowDefinitionId}";
            var correlationId         = request.CorrelationId;
            var correlationLockHandle = default(IDistributedSynchronizationHandle?);

            if (!string.IsNullOrWhiteSpace(correlationId))
            {
                _logger.LogDebug("Acquiring lock on correlation ID {CorrelationId}", correlationId);
                correlationLockHandle = await _distributedLockProvider.AcquireLockAsync(correlationId, _elsaOptions.DistributedLockTimeout, cancellationToken);

                if (correlationLockHandle == null)
                {
                    throw new LockAcquisitionException($"Failed to acquire a lock on correlation ID {correlationId}");
                }
            }

            try
            {
                await using var handle = await _distributedLockProvider.AcquireLockAsync(lockKey, _elsaOptions.DistributedLockTimeout, cancellationToken);

                if (handle == null)
                {
                    throw new LockAcquisitionException($"Failed to acquire a lock on {lockKey}");
                }

                if (!workflowBlueprint !.IsSingleton || await GetWorkflowIsAlreadyExecutingAsync(tenantId, workflowDefinitionId) == false)
                {
                    await _startsWorkflow.StartWorkflowAsync(workflowBlueprint, request.ActivityId, request.Input, request.CorrelationId, request.ContextId, cancellationToken);
                }
            }
            finally
            {
                if (correlationLockHandle != null)
                {
                    await correlationLockHandle.DisposeAsync();
                }
            }

            return(Unit.Value);
        }
Ejemplo n.º 5
0
        public async Task <ActionResult <WorkflowBlueprintModel> > Handle(string id, VersionOptions?versionOptions = default, CancellationToken cancellationToken = default)
        {
            versionOptions ??= VersionOptions.Latest;
            var workflowBlueprint = await _workflowRegistry.GetAsync(id, null, versionOptions.Value, cancellationToken, true);

            if (workflowBlueprint == null)
            {
                return(NotFound());
            }

            var model = await _workflowBlueprintMapper.MapAsync(workflowBlueprint, cancellationToken);

            return(Json(model, _contentSerializer.GetSettings()));
        }
Ejemplo n.º 6
0
        public async Task <RunWorkflowResult> ResumeWorkflowAsync(WorkflowInstance workflowInstance, string?activityId = default, object?input = default, CancellationToken cancellationToken = default)
        {
            var workflowBlueprint = await _workflowRegistry.GetAsync(
                workflowInstance.DefinitionId,
                workflowInstance.TenantId,
                VersionOptions.SpecificVersion(workflowInstance.Version),
                cancellationToken);

            if (workflowBlueprint == null)
            {
                throw new WorkflowException($"Workflow instance {workflowInstance.Id} references workflow definition {workflowInstance.DefinitionId} version {workflowInstance.Version}, but no such workflow definition was found.");
            }

            return(await _workflowRunner.RunWorkflowAsync(workflowBlueprint, workflowInstance, activityId, input, cancellationToken));
        }
Ejemplo n.º 7
0
        public async Task <RunWorkflowResult?> FindAndRestartTestWorkflowAsync(
            string workflowDefinitionId,
            string activityId,
            int version,
            string signalRConnectionId,
            string lastWorkflowInstanceId,
            string?tenantId = default,
            CancellationToken cancellationToken = default)
        {
            var workflowBlueprint = await _workflowRegistry.GetAsync(workflowDefinitionId, tenantId, VersionOptions.SpecificVersion(version), cancellationToken);

            if (workflowBlueprint == null)
            {
                return(null);
            }

            var lastWorkflowInstance = await _workflowInstanceStore.FindAsync(new EntityIdSpecification <WorkflowInstance>(lastWorkflowInstanceId), cancellationToken);

            if (lastWorkflowInstance == null)
            {
                return(null);
            }

            var startActivity = workflowBlueprint.Activities.First(x => x.Id == activityId);

            var startableWorkflowDefinition = new StartableWorkflowDefinition(workflowBlueprint, startActivity.Id);

            var workflow = await InstantiateStartableWorkflow(startableWorkflowDefinition, cancellationToken);

            var previousActivityData = GetActivityDataFromLastWorkflowInstance(workflow.WorkflowInstance, lastWorkflowInstance, workflowBlueprint, activityId);

            MergeActivityDataIntoInstance(workflow.WorkflowInstance, previousActivityData);

            SetMetadata(workflow.WorkflowInstance, signalRConnectionId);

            //if previousActivityOutput has any items, then the first one is from activity closest to the starting one
            var previousActivityOutput = previousActivityData.Count == 0 ? null : previousActivityData.First().Value?.GetItem("Output");

            return(await ExecuteStartableWorkflowAsync(workflow, new WorkflowInput(previousActivityOutput), cancellationToken));
        }
Ejemplo n.º 8
0
        public async Task Handle(ExecuteWorkflowDefinitionRequest message)
        {
            var workflowDefinitionId = message.WorkflowDefinitionId;
            var tenantId             = message.TenantId;
            var workflowBlueprint    = await _workflowRegistry.GetAsync(workflowDefinitionId, tenantId, VersionOptions.Published);

            if (workflowBlueprint == null)
            {
                _logger.LogWarning("Could not find workflow with ID {WorkflowDefinitionId}", workflowDefinitionId);
                return;
            }

            var startableWorkflow = await _workflowLaunchpad.CollectStartableWorkflowAsync(workflowBlueprint, message.ActivityId, message.CorrelationId, message.ContextId, tenantId);

            if (startableWorkflow == null)
            {
                _logger.LogDebug("Could not start workflow with ID {WorkflowDefinitionId}", workflowDefinitionId);
                return;
            }

            await _workflowLaunchpad.ExecuteStartableWorkflowAsync(startableWorkflow, message.Input);
        }
Ejemplo n.º 9
0
 private async Task <IWorkflowBlueprint?> GetWorkflowBlueprintAsync(WorkflowInstance workflowInstance, CancellationToken cancellationToken) =>
 await _workflowRegistry.GetAsync(workflowInstance.DefinitionId, workflowInstance.TenantId, VersionOptions.SpecificVersion(workflowInstance.Version), cancellationToken);
Ejemplo n.º 10
0
 public static Task <IWorkflowBlueprint?> GetWorkflowAsync <T>(
     this IWorkflowRegistry workflowRegistry,
     string?tenantId,
     CancellationToken cancellationToken = default) =>
 workflowRegistry.GetAsync(typeof(T).Name, tenantId, VersionOptions.Latest, cancellationToken);