Example #1
0
    public async Task <IEnumerable <CollectedWorkflow> > DispatchUserActionsAsync(TriggerUserAction taskAction, CancellationToken cancellationToken = default)
    {
        var bookmark = new UserTaskBookmark(taskAction.Action);
        var query    = new WorkflowsQuery(nameof(Activities.UserTask), bookmark, taskAction.CorrelationId, taskAction.WorkflowInstanceId);

        return(await _workflowLaunchpad.CollectAndDispatchWorkflowsAsync(query, new WorkflowInput(taskAction.Action), cancellationToken : cancellationToken));
    }
Example #2
0
        private async Task TriggerWorkflowsAsync(ServiceBusMessage message, CancellationToken cancellationToken)
        {
            var correlationId = message.CorrelationId;

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

            var bookmark      = new MessageReceivedBookmark(QueueOrTopic, Subscription);
            var launchContext = new WorkflowsQuery(ActivityType, bookmark, correlationId);

            using var scope = _serviceScopeFactory.CreateScope();
            var workflowLaunchpad = scope.ServiceProvider.GetRequiredService <IWorkflowLaunchpad>();
            await workflowLaunchpad.CollectAndDispatchWorkflowsAsync(launchContext, new WorkflowInput(model), cancellationToken);
        }
Example #3
0
        public async Task <IActionResult> Handle(TriggerWorkflowsRequestModel request, CancellationToken cancellationToken = default)
        {
            var tenantId = await _tenantAccessor.GetTenantIdAsync(cancellationToken);

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

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

                triggeredWorkflows = result.Select(x => new TriggeredWorkflowModel(x.WorkflowInstanceId, x.ActivityId)).ToList();
            }
            else
            {
                var result = await _workflowLaunchpad.CollectAndExecuteWorkflowsAsync(context, new WorkflowInput(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)));
        }
Example #4
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 launchContext = new WorkflowsQuery(ActivityType, bookmark, correlationId);

            await _workflowLaunchpad.UseServiceAsync(service => service.CollectAndDispatchWorkflowsAsync(launchContext, new WorkflowInput(model), cancellationToken));
        }
Example #5
0
        public async Task Consume(ConsumeContext <T> context)
        {
            var message       = context.Message;
            var correlationId = default(Guid?);

            foreach (var item in CorrelationIdSelectors)
            {
                if (item.TryGetCorrelationId(message, out correlationId))
                {
                    break;
                }
            }

            var bookmark = new MessageReceivedBookmark
            {
                MessageType = message.GetType().Name
            };

            var workflowQuery = new WorkflowsQuery(
                nameof(ReceiveMassTransitMessage),
                bookmark,
                correlationId.ToString()
                );

            var workflowInput = new WorkflowInput {
                Input = message
            };

            await _workflowLaunchpad.CollectAndExecuteWorkflowsAsync(workflowQuery, workflowInput, context.CancellationToken);
        }
Example #6
0
        private async Task TriggerWorkflowsAsync(MqttApplicationMessage message, CancellationToken cancellationToken)
        {
            var bookmark      = CreateBookmark(_receiverClient.Options);
            var launchContext = new WorkflowsQuery(ActivityType, bookmark);

            await _workflowLaunchpad.UseServiceAsync(service => service.CollectAndDispatchWorkflowsAsync(launchContext, new WorkflowInput(message), cancellationToken));
        }
Example #7
0
        private async Task TriggerWorkflowsAsync(MqttApplicationMessage message, CancellationToken cancellationToken)
        {
            var bookmark      = CreateBookmark(_receiverClient.Options);
            var launchContext = new WorkflowsQuery(ActivityType, bookmark);

            using var scope = _serviceScopeFactory.CreateScope();
            var workflowLaunchpad = scope.ServiceProvider.GetRequiredService <IWorkflowLaunchpad>();
            await workflowLaunchpad.CollectAndDispatchWorkflowsAsync(launchContext, new WorkflowInput(message), cancellationToken);
        }
Example #8
0
        private async Task TriggerWorkflowsAsync(TransportMessage message, CancellationToken cancellationToken)
        {
            //avoid handler being triggered earlier than workflow is suspended
            await Task.Delay(_delay, cancellationToken);

            var config = _client.Configuration;

            var bookmark      = new MessageReceivedBookmark(config.ExchangeName, config.RoutingKey, config.ConnectionString, config.Headers);
            var launchContext = new WorkflowsQuery(ActivityType, bookmark);

            await _workflowLaunchpad.UseServiceAsync(service => service.CollectAndDispatchWorkflowsAsync(launchContext, new WorkflowInput(message), cancellationToken));
        }
Example #9
0
        private async Task TriggerWorkflowsAsync(TransportMessage message, CancellationToken cancellationToken)
        {
            //avoid handler being triggered earlier than workflow is suspended
            await Task.Delay(_delay, cancellationToken);

            var config = _client.Configuration;

            var bookmark      = new MessageReceivedBookmark(config.ExchangeName, config.RoutingKey, config.ConnectionString, config.Headers);
            var launchContext = new WorkflowsQuery(ActivityType, bookmark);

            using var scope = _scopeFactory.CreateScope();
            var workflowLaunchpad = scope.ServiceProvider.GetRequiredService <IWorkflowLaunchpad>();
            await workflowLaunchpad.CollectAndDispatchWorkflowsAsync(launchContext, new WorkflowInput(message), cancellationToken);
        }
        public async Task <IEnumerable <CollectedWorkflow> > FindWorkflowsAsync(WorkflowsQuery query, CancellationToken cancellationToken = default)
        {
            var correlationId = query.CorrelationId;

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

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

            return(await CollectResumableAndStartableWorkflowsAsync(query, cancellationToken));
        }
Example #11
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 = payload.GetCorrelationId();
            var bookmark      = new NotificationBookmark(eventType);
            var context       = new WorkflowsQuery(activityType, bookmark, correlationId);
            await _workflowLaunchpad.CollectAndDispatchWorkflowsAsync(context, new WorkflowInput(webhook), cancellationToken).ToList();
        }
        public async Task Handle(TelnyxWebhookReceived notification, CancellationToken cancellationToken)
        {
            var webhook = notification.Webhook;

            if (webhook.Data.Payload is not CallInitiatedPayload payload)
            {
                return;
            }

            var correlationId = GetCorrelationId(payload);
            var toBookmark    = new FilteredCallInitiatedToBookmark(payload.To);
            var toQuery       = new WorkflowsQuery(nameof(FilteredCallInitiated), toBookmark, correlationId);
            var fromBookmark  = new FilteredCallInitiatedToBookmark(payload.From);
            var fromQuery     = new WorkflowsQuery(nameof(FilteredCallInitiated), fromBookmark, correlationId);

            await _workflowLaunchpad.CollectAndDispatchWorkflowsAsync(toQuery, new WorkflowInput(webhook), cancellationToken);

            await _workflowLaunchpad.CollectAndDispatchWorkflowsAsync(fromQuery, new WorkflowInput(webhook), cancellationToken);
        }
        public async Task <IEnumerable <StartableWorkflow> > FindStartableWorkflowsAsync(WorkflowsQuery query, CancellationToken cancellationToken = default)
        {
            var correlationId  = query.CorrelationId ?? Guid.NewGuid().ToString("N");
            var updatedContext = query with {
                CorrelationId = correlationId
            };

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

            var startableWorkflowDefinitions = await CollectStartableWorkflowsInternalAsync(updatedContext, cancellationToken);

            return(await InstantiateStartableWorkflows(startableWorkflowDefinitions, cancellationToken).ToList());
        }
Example #14
0
        public async Task <IEnumerable <CollectedWorkflow> > CollectAndDispatchWorkflowsAsync(WorkflowsQuery query, WorkflowInput?input = default, CancellationToken cancellationToken = default)
        {
            var pendingWorkflows = await FindWorkflowsAsync(query, cancellationToken).ToList();

            await DispatchPendingWorkflowsAsync(pendingWorkflows, input, cancellationToken);

            return(pendingWorkflows);
        }
Example #15
0
        public async Task <IEnumerable <CollectedWorkflow> > CollectResumableAndStartableWorkflowsAsync(WorkflowsQuery query, CancellationToken cancellationToken)
        {
            var bookmarkResultsQuery = query.Bookmark != null ? await _bookmarkFinder.FindBookmarksAsync(query.ActivityType, query.Bookmark, query.CorrelationId, query.TenantId, cancellationToken) : default;

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

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

            return(pendingWorkflows);
        }
Example #16
0
        private async Task <IEnumerable <StartableWorkflow> > CollectStartableWorkflowsInternalAsync(WorkflowsQuery query, CancellationToken cancellationToken = default)
        {
            _logger.LogDebug("Triggering workflows using {ActivityType}", query.ActivityType);

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

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

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

            return(startableWorkflows);
        }
Example #17
0
        private async Task <IEnumerable <CollectedWorkflow> > CollectSpecificWorkflowInstanceAsync(WorkflowsQuery query, CancellationToken cancellationToken)
        {
            var bookmarkResultsQuery = query.Bookmark != null ? await _bookmarkFinder.FindBookmarksAsync(query.ActivityType, query.Bookmark, query.CorrelationId, query.TenantId, cancellationToken) : default;

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

            return(pendingWorkflows);
        }
Example #18
0
        public async Task <IEnumerable <CollectedWorkflow> > CollectAndExecuteWorkflowsAsync(WorkflowsQuery query, WorkflowInput?input = default, CancellationToken cancellationToken = default)
        {
            var pendingWorkflows = await FindWorkflowsAsync(query, cancellationToken).ToList();

            await ExecutePendingWorkflowsAsync(pendingWorkflows, input, cancellationToken);

            return(pendingWorkflows.Select(x => new CollectedWorkflow(x.WorkflowInstanceId, x.ActivityId)));
        }
Example #19
0
        private async Task <IEnumerable <CollectedWorkflow> > CollectResumableOrStartableCorrelatedWorkflowsAsync(WorkflowsQuery query, CancellationToken cancellationToken)
        {
            var correlationId = query.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 = query.Bookmark != null
                    ? await _bookmarkFinder.FindBookmarksAsync(query.ActivityType, query.Bookmark, correlationId, query.TenantId, cancellationToken).ToList()
                    : new List <BookmarkFinderResult>();

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

            var startableWorkflows = await CollectStartableWorkflowsInternalAsync(query, cancellationToken);

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