2025-04-01 05:53:00 +00:00
|
|
|
|
using Elsa.Extensions;
|
|
|
|
|
|
using Elsa.Features.Services;
|
|
|
|
|
|
using Elsa.Mediator.Contracts;
|
|
|
|
|
|
using Elsa.Workflows;
|
|
|
|
|
|
using Elsa.Workflows.Notifications;
|
|
|
|
|
|
using Elsa.Workflows.Runtime;
|
|
|
|
|
|
using Elsa.Workflows.Runtime.Contracts;
|
2025-09-25 18:58:21 +00:00
|
|
|
|
using Elsa.Workflows.Runtime.Notifications;
|
2025-04-01 05:53:00 +00:00
|
|
|
|
using Elsa.Workflows.Runtime.Requests;
|
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
|
using Microsoft.Extensions.Hosting;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Elsa.Testing.Shared;
|
|
|
|
|
|
|
|
|
|
|
|
public static class DispatchWorkflowExtensions
|
|
|
|
|
|
{
|
2025-09-25 18:58:21 +00:00
|
|
|
|
public static async Task<WorkflowStateCommitted?> DispatchWorkflowAndRunToCompletion(
|
2025-04-01 05:53:00 +00:00
|
|
|
|
this IWorkflow workflowDefinition,
|
|
|
|
|
|
Action<IServiceCollection>? configureServices = null,
|
|
|
|
|
|
Action<IModule>? configureElsa = null,
|
|
|
|
|
|
string? instanceId = null,
|
|
|
|
|
|
TimeSpan? timeout = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var semaphore = new SemaphoreSlim(0, 1);
|
2025-09-25 18:58:21 +00:00
|
|
|
|
WorkflowStateCommitted? workflowFinishedRecord = null;
|
2025-04-01 05:53:00 +00:00
|
|
|
|
|
|
|
|
|
|
var host = Host.CreateDefaultBuilder()
|
|
|
|
|
|
.ConfigureServices(services =>
|
|
|
|
|
|
{
|
|
|
|
|
|
configureServices?.Invoke(services);
|
|
|
|
|
|
|
|
|
|
|
|
// This notification handler will capture the WorkflowFinished record (to be returned) and release the semaphore.
|
2025-09-25 18:58:21 +00:00
|
|
|
|
services.AddNotificationHandler<WorkflowFinishedAction, WorkflowStateCommitted>(sp => new(notification =>
|
2025-04-01 05:53:00 +00:00
|
|
|
|
{
|
2025-09-25 18:58:21 +00:00
|
|
|
|
if (notification.WorkflowExecutionContext.Status != WorkflowStatus.Finished)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2025-04-01 05:53:00 +00:00
|
|
|
|
workflowFinishedRecord = notification;
|
|
|
|
|
|
semaphore.Release();
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
services.AddElsa(elsa => configureElsa?.Invoke(elsa));
|
|
|
|
|
|
})
|
|
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// Start the host.
|
|
|
|
|
|
await host.StartAsync(CancellationToken.None);
|
|
|
|
|
|
using var scope = host.Services.CreateScope();
|
|
|
|
|
|
var serviceProvider = scope.ServiceProvider;
|
|
|
|
|
|
await serviceProvider.PopulateRegistriesAsync();
|
|
|
|
|
|
|
|
|
|
|
|
// Build the workflow
|
|
|
|
|
|
var workflowBuilderFactory = serviceProvider.GetRequiredService<IWorkflowBuilderFactory>();
|
|
|
|
|
|
var workflow = await workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync(workflowDefinition);
|
|
|
|
|
|
|
|
|
|
|
|
// Register the workflow
|
|
|
|
|
|
var workflowRegistry = serviceProvider.GetRequiredService<IWorkflowRegistry>();
|
|
|
|
|
|
await workflowRegistry.RegisterAsync(workflow);
|
|
|
|
|
|
|
|
|
|
|
|
// Dispatch the workflow
|
|
|
|
|
|
var workflowDispatcher = serviceProvider.GetRequiredService<IWorkflowDispatcher>();
|
|
|
|
|
|
var dispatchWorkflowResponse = await workflowDispatcher.DispatchAsync(new DispatchWorkflowDefinitionRequest
|
|
|
|
|
|
{
|
2025-11-12 15:56:31 +00:00
|
|
|
|
DefinitionVersionId = workflow.DefinitionHandle.DefinitionVersionId!,
|
2025-04-01 05:53:00 +00:00
|
|
|
|
InstanceId = instanceId ?? Guid.NewGuid().ToString(),
|
|
|
|
|
|
});
|
|
|
|
|
|
dispatchWorkflowResponse.ThrowIfFailed();
|
|
|
|
|
|
|
|
|
|
|
|
// Wait for the workflow to complete, and then return the WorkflowFinished notification.
|
2025-06-03 07:58:20 +00:00
|
|
|
|
var signaled = await semaphore.WaitAsync(timeout ?? TimeSpan.FromSeconds(50000));
|
2025-04-01 05:53:00 +00:00
|
|
|
|
return signaled ? workflowFinishedRecord : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
// Stop the host.
|
|
|
|
|
|
await host.StopAsync(CancellationToken.None);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-25 18:58:21 +00:00
|
|
|
|
class WorkflowFinishedAction(Action<WorkflowStateCommitted> action) : INotificationHandler<WorkflowStateCommitted>
|
2025-04-01 05:53:00 +00:00
|
|
|
|
{
|
2025-09-25 18:58:21 +00:00
|
|
|
|
public Task HandleAsync(WorkflowStateCommitted notification, CancellationToken cancellationToken)
|
2025-04-01 05:53:00 +00:00
|
|
|
|
{
|
|
|
|
|
|
action(notification);
|
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|