Exemple #1
0
        private async Task TriggerWorkflowsAsync(Message message, CancellationToken cancellationToken)
        {
            var correlationId = message.CorrelationId;

            var model = new MessageModel
            {
                Body                    = message.Body,
                CorrelationId           = message.CorrelationId,
                ContentType             = message.ContentType,
                Label                   = message.Label,
                To                      = message.To,
                MessageId               = message.MessageId,
                PartitionKey            = message.PartitionKey,
                ViaPartitionKey         = message.ViaPartitionKey,
                ReplyTo                 = message.ReplyTo,
                SessionId               = message.SessionId,
                ExpiresAtUtc            = message.ExpiresAtUtc,
                TimeToLive              = message.TimeToLive,
                ReplyToSessionId        = message.ReplyToSessionId,
                ScheduledEnqueueTimeUtc = message.ScheduledEnqueueTimeUtc,
                UserProperties          = new Dictionary <string, object>(message.UserProperties),
            };

            var bookmark      = CreateBookmark(message);
            var trigger       = CreateTrigger(message);
            var launchContext = new CollectWorkflowsContext(ActivityType, bookmark, trigger, correlationId);

            await _workflowLaunchpad.UseServiceAsync(service => service.CollectAndDispatchWorkflowsAsync(launchContext, model, cancellationToken));
        }
Exemple #2
0
        public async Task <IActionResult> Handle(TriggerWorkflowsRequestModel request, CancellationToken cancellationToken = default)
        {
            var tenantId = await _tenantAccessor.GetTenantIdAsync(cancellationToken);

            var context = new CollectWorkflowsContext(request.ActivityType, request.Bookmark, request.Trigger, request.CorrelationId, request.WorkflowInstanceId, request.ContextId, tenantId);
            ICollection <TriggeredWorkflowModel> triggeredWorkflows;

            if (request.Dispatch)
            {
                var result = await _workflowLaunchpad.CollectAndDispatchWorkflowsAsync(context, request.Input, cancellationToken).ToList();

                triggeredWorkflows = result.Select(x => new TriggeredWorkflowModel(x.WorkflowInstanceId, x.ActivityId)).ToList();
            }
            else
            {
                var result = await _workflowLaunchpad.CollectAndExecuteWorkflowsAsync(context, request.Input, cancellationToken).ToList();

                triggeredWorkflows = result.Select(x => new TriggeredWorkflowModel(x.WorkflowInstanceId, x.ActivityId)).ToList();
            }

            if (Response.HasStarted)
            {
                return(new EmptyResult());
            }

            return(Ok(new TriggerWorkflowsResponseModel(triggeredWorkflows)));
        }
Exemple #3
0
        public async Task <IActionResult> Handle(ExecuteWorkflowsRequest request, CancellationToken cancellationToken = default)
        {
            var context = new CollectWorkflowsContext(request.ActivityType, request.Bookmark, request.Trigger, request.CorrelationId, request.WorkflowInstanceId, request.ContextId);
            var result  = await _workflowLaunchpad.CollectAndExecuteWorkflowsAsync(context, request.Input, cancellationToken).ToList();

            if (Response.HasStarted)
            {
                return(new EmptyResult());
            }

            return(Ok(new ExecuteWorkflowsResponse(result)));
        }
        public async Task <IEnumerable <PendingWorkflow> > CollectWorkflowsAsync(CollectWorkflowsContext context, CancellationToken cancellationToken = default)
        {
            var correlationId = context.CorrelationId;

            if (!string.IsNullOrWhiteSpace(correlationId))
            {
                return(await CollectResumableOrStartableCorrelatedWorkflowsAsync(context, cancellationToken));
            }

            if (!string.IsNullOrWhiteSpace(context.WorkflowInstanceId))
            {
                return(await CollectSpecificWorkflowInstanceAsync(context, cancellationToken));
            }

            return(await CollectResumableAndStartableWorkflowsAsync(context, cancellationToken));
        }
Exemple #5
0
        public async Task Handle(TelnyxWebhookReceived notification, CancellationToken cancellationToken)
        {
            var webhook      = notification.Webhook;
            var eventType    = webhook.Data.EventType;
            var payload      = webhook.Data.Payload;
            var activityType = _webhookFilterService.GetActivityTypeName(payload);

            if (activityType == null)
            {
                _logger.LogWarning("The received event '{EventType}' is an unsupported event", webhook.Data.EventType);
                return;
            }

            var correlationId = GetCorrelationId(payload);
            var bookmark      = new NotificationBookmark(eventType);
            var trigger       = new NotificationBookmark(eventType);
            var context       = new CollectWorkflowsContext(activityType, bookmark, trigger, correlationId);

            await _workflowLaunchpad.CollectAndDispatchWorkflowsAsync(context, webhook, cancellationToken);
        }
        public async Task <IEnumerable <StartableWorkflow> > CollectStartableWorkflowsAsync(CollectWorkflowsContext context, CancellationToken cancellationToken = default)
        {
            _logger.LogDebug("Triggering workflows using {ActivityType}", context.ActivityType);

            var filter             = context.Trigger;
            var triggers           = filter != null ? (await _triggerFinder.FindTriggersAsync(context.ActivityType, filter, context.TenantId, cancellationToken)).ToList() : new List <TriggerFinderResult>();
            var startableWorkflows = new List <StartableWorkflow>();

            foreach (var trigger in triggers)
            {
                var workflowBlueprint = trigger.WorkflowBlueprint;
                var startableWorkflow = await CollectStartableWorkflowAsync(workflowBlueprint, trigger.ActivityId, context.CorrelationId, context.ContextId, context.TenantId, cancellationToken);

                if (startableWorkflow != null)
                {
                    startableWorkflows.Add(startableWorkflow);
                }
            }

            return(startableWorkflows);
        }
        private async Task <IEnumerable <PendingWorkflow> > CollectResumableOrStartableCorrelatedWorkflowsAsync(CollectWorkflowsContext context, CancellationToken cancellationToken)
        {
            var correlationId = context.CorrelationId !;
            var lockKey       = correlationId;

            _logger.LogDebug("Acquiring lock on correlation ID {CorrelationId}", correlationId);
            await using (var handle = await _distributedLockProvider.AcquireLockAsync(lockKey, _elsaOptions.DistributedLockTimeout, cancellationToken))
            {
                if (handle == null)
                {
                    throw new LockAcquisitionException($"Failed to acquire a lock on {lockKey}");
                }

                var correlatedWorkflowInstanceCount = !string.IsNullOrWhiteSpace(correlationId)
                    ? await _workflowInstanceStore.CountAsync(new CorrelationIdSpecification <WorkflowInstance>(correlationId).WithStatus(WorkflowStatus.Suspended), cancellationToken)
                    : 0;

                _logger.LogDebug("Found {CorrelatedWorkflowCount} correlated workflows,", correlatedWorkflowInstanceCount);

                if (correlatedWorkflowInstanceCount > 0)
                {
                    _logger.LogDebug("{WorkflowInstanceCount} existing workflows found with correlation ID '{CorrelationId}' will be queued for execution", correlatedWorkflowInstanceCount, correlationId);
                    var bookmarkResults = context.Bookmark != null ? await _bookmarkFinder.FindBookmarksAsync(context.ActivityType, context.Bookmark, correlationId, context.TenantId, cancellationToken).ToList() : new List <BookmarkFinderResult>();

                    return(bookmarkResults.Select(x => new PendingWorkflow(x.WorkflowInstanceId, x.ActivityId)).ToList());
                }
            }

            var startableWorkflows = await CollectStartableWorkflowsAsync(context, cancellationToken);

            return(startableWorkflows.Select(x => new PendingWorkflow(x.WorkflowInstance.Id, x.ActivityId)).ToList());
        }
        private async Task <IEnumerable <PendingWorkflow> > CollectSpecificWorkflowInstanceAsync(CollectWorkflowsContext context, CancellationToken cancellationToken)
        {
            var bookmarkResultsQuery = context.Bookmark != null ? await _bookmarkFinder.FindBookmarksAsync(context.ActivityType, context.Bookmark, context.CorrelationId, context.TenantId, cancellationToken) : default;

            bookmarkResultsQuery = bookmarkResultsQuery?.Where(x => x.WorkflowInstanceId == context.WorkflowInstanceId);
            var bookmarkResults  = bookmarkResultsQuery?.ToList() ?? new List <BookmarkFinderResult>();
            var pendingWorkflows = bookmarkResults.Select(x => new PendingWorkflow(x.WorkflowInstanceId, x.ActivityId)).ToList();

            return(pendingWorkflows);
        }
        public async Task <IEnumerable <PendingWorkflow> > CollectResumableAndStartableWorkflowsAsync(CollectWorkflowsContext context, CancellationToken cancellationToken)
        {
            var bookmarkResultsQuery = context.Bookmark != null ?await _bookmarkFinder.FindBookmarksAsync(context.ActivityType, context.Bookmark, context.CorrelationId, context.TenantId, cancellationToken) : default;

            var bookmarkResults           = bookmarkResultsQuery?.ToList() ?? new List <BookmarkFinderResult>();
            var triggeredPendingWorkflows = bookmarkResults.Select(x => new PendingWorkflow(x.WorkflowInstanceId, x.ActivityId)).ToList();
            var startableWorkflows        = await CollectStartableWorkflowsAsync(context, cancellationToken);

            var pendingWorkflows = triggeredPendingWorkflows.Concat(startableWorkflows.Select(x => new PendingWorkflow(x.WorkflowInstance.Id, x.ActivityId))).Distinct().ToList();

            return(pendingWorkflows);
        }
Exemple #10
0
        public async Task <IEnumerable <PendingWorkflow> > CollectAndDispatchWorkflowsAsync(CollectWorkflowsContext context, object?input = default, CancellationToken cancellationToken = default)
        {
            var pendingWorkflows = await CollectWorkflowsAsync(context, cancellationToken).ToList();

            await DispatchPendingWorkflowsAsync(pendingWorkflows, input, cancellationToken);

            return(pendingWorkflows);
        }
Exemple #11
0
        public async Task <IEnumerable <StartedWorkflow> > CollectAndExecuteWorkflowsAsync(CollectWorkflowsContext context, object?input = default, CancellationToken cancellationToken = default)
        {
            var pendingWorkflows = await CollectWorkflowsAsync(context, cancellationToken).ToList();

            await ExecutePendingWorkflowsAsync(pendingWorkflows, input, cancellationToken);

            return(pendingWorkflows.Select(x => new StartedWorkflow(x.WorkflowInstanceId, x.ActivityId)));
        }
        public async Task <IEnumerable <StartableWorkflow> > CollectStartableWorkflowsAsync(CollectWorkflowsContext context, CancellationToken cancellationToken = default)
        {
            var correlationId  = context.CorrelationId ?? Guid.NewGuid().ToString("N");
            var updatedContext = context with {
                CorrelationId = correlationId
            };

            await using var lockHandle = await AcquireLockAsync(correlationId, cancellationToken);

            return(await CollectStartableWorkflowsInternalAsync(updatedContext, cancellationToken));
        }
        private async Task <IEnumerable <CollectedWorkflow> > CollectResumableOrStartableCorrelatedWorkflowsAsync(CollectWorkflowsContext context, CancellationToken cancellationToken)
        {
            var correlationId = context.CorrelationId !;

            await using var handle = await AcquireLockAsync(correlationId, cancellationToken);

            var correlatedWorkflowInstanceCount = !string.IsNullOrWhiteSpace(correlationId)
                ? await _workflowInstanceStore.CountAsync(new CorrelationIdSpecification <WorkflowInstance>(correlationId).And(new WorkflowUnfinishedStatusSpecification()), cancellationToken)
                : 0;

            _logger.LogDebug("Found {CorrelatedWorkflowCount} workflows with correlation ID {CorrelationId}", correlatedWorkflowInstanceCount, correlationId);

            if (correlatedWorkflowInstanceCount > 0)
            {
                var bookmarkResults = context.Bookmark != null
                    ? await _bookmarkFinder.FindBookmarksAsync(context.ActivityType, context.Bookmark, correlationId, context.TenantId, cancellationToken).ToList()
                    : new List <BookmarkFinderResult>();

                _logger.LogDebug("Found {BookmarkCount} bookmarks for activity type {ActivityType}", bookmarkResults.Count, context.ActivityType);
                return(bookmarkResults.Select(x => new CollectedWorkflow(x.WorkflowInstanceId, x.ActivityId)).ToList());
            }

            var startableWorkflows = await CollectStartableWorkflowsInternalAsync(context, cancellationToken);

            return(startableWorkflows.Select(x => new CollectedWorkflow(x.WorkflowInstance.Id, x.ActivityId)).ToList());
        }