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); } }
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); }
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); }