Beispiel #1
0
        public async Task ExecuteAsync(CancellationToken cancellationToken = default)
        {
            await using var handle = await _distributedLockProvider.AcquireLockAsync(GetType ().Name, _elsaOptions.DistributedLockTimeout, cancellationToken);

            if (handle == null)
            {
                return;
            }

            var instances = await _workflowInstanceStore.FindManyAsync(new WorkflowStatusSpecification(WorkflowStatus.Running), cancellationToken : cancellationToken).ToList();

            if (instances.Any())
            {
                _logger.LogInformation("Found {WorkflowInstanceCount} workflows with status 'Running'. Resuming each one of them", instances.Count);
            }
            else
            {
                _logger.LogInformation("Found no workflows with status 'Running'. Nothing to resume");
            }

            foreach (var instance in instances)
            {
                await using var correlationLockHandle = await _distributedLockProvider.AcquireLockAsync(instance.CorrelationId, _elsaOptions.DistributedLockTimeout, cancellationToken);

                if (handle == null)
                {
                    _logger.LogWarning("Failed to acquire lock on correlation {CorrelationId} for workflow instance {WorkflowInstanceId}", instance.CorrelationId, instance.Id);
                    continue;
                }

                _logger.LogInformation("Resuming {WorkflowInstanceId}", instance.Id);
                var scheduledActivities = instance.ScheduledActivities;

                if (instance.CurrentActivity == null && !scheduledActivities.Any())
                {
                    if (instance.BlockingActivities.Any())
                    {
                        _logger.LogWarning(
                            "Workflow '{WorkflowInstanceId}' was in the Running state, but has no scheduled activities not has a currently executing one. However, it does have blocking activities, so switching to Suspended status",
                            instance.Id);

                        instance.WorkflowStatus = WorkflowStatus.Suspended;
                        await _workflowInstanceStore.SaveAsync(instance, cancellationToken);

                        continue;
                    }

                    _logger.LogWarning("Workflow '{WorkflowInstanceId}' was in the Running state, but has no scheduled activities nor has a currently executing one", instance.Id);
                    continue;
                }

                var scheduledActivity = instance.CurrentActivity ?? instance.ScheduledActivities.Peek();

                await _workflowInstanceDispatcher.DispatchAsync(new ExecuteWorkflowInstanceRequest(instance.Id, scheduledActivity.ActivityId), cancellationToken);
            }
        }
Beispiel #2
0
        public async Task ExecuteAsync(CancellationToken cancellationToken = default)
        {
            await using var handle = await _distributedLockProvider.AcquireLockAsync(GetType ().Name, _elsaOptions.DistributedLockTimeout, cancellationToken);

            if (handle == null)
            {
                return;
            }

            await ResumeIdleWorkflows(cancellationToken);
            await ResumeRunningWorkflowsAsync(cancellationToken);
        }
Beispiel #3
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);
        }