using Elsa.Common.Models; using Elsa.Workflows; using Elsa.Workflows.Contracts; using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Models; using Elsa.Workflows.Options; using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Options; using Elsa.Workflows.State; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Testing.Shared; /// /// Provides extension methods for . /// [PublicAPI] public static class ServiceProviderExtensions { /// /// Updates the registries. /// /// The services. public static Task PopulateRegistriesAsync(this IServiceProvider services) { var registriesPopulator = services.GetRequiredService(); return registriesPopulator.PopulateAsync(); } /// /// Imports a workflow definition from a file. /// /// The services. /// The file name. /// The workflow definition. public static async Task ImportWorkflowDefinitionAsync(this IServiceProvider services, string fileName) { var json = await File.ReadAllTextAsync(fileName); var serializer = services.GetRequiredService(); var model = serializer.Deserialize(json); var workflowDefinitionRequest = new SaveWorkflowDefinitionRequest { Model = model, Publish = true }; var workflowDefinitionImporter = services.GetRequiredService(); var result = await workflowDefinitionImporter.ImportAsync(workflowDefinitionRequest); return result.WorkflowDefinition; } /// /// Runs a workflow until its end, automatically resuming any bookmark it encounters. /// /// The services. /// The ID of the workflow definition. /// An optional dictionary of input values. /// The workflow state. public static async Task RunWorkflowUntilEndAsync(this IServiceProvider services, string workflowDefinitionId, IDictionary? input = default) { var startWorkflowOptions = new StartWorkflowRuntimeOptions { Input = input, VersionOptions = VersionOptions.Published }; var workflowRuntime = services.GetRequiredService(); var result = await workflowRuntime.StartWorkflowAsync(workflowDefinitionId, startWorkflowOptions); var bookmarks = new Stack(result.Bookmarks); // Continue resuming the workflow for as long as there are bookmarks to resume and the workflow is not Finished. while (result.Status != WorkflowStatus.Finished && bookmarks.TryPop(out var bookmark)) { var resumeOptions = new ResumeWorkflowRuntimeOptions { BookmarkId = bookmark.Id }; var resumeResult = await workflowRuntime.ResumeWorkflowAsync(result.WorkflowInstanceId, resumeOptions); foreach (var newBookmark in resumeResult!.Bookmarks) bookmarks.Push(newBookmark); } // Return the workflow state. return (await workflowRuntime.ExportWorkflowStateAsync(result.WorkflowInstanceId))!; } /// /// Runs a workflow until its end, automatically resuming any bookmark it encounters. /// public static async Task RunWorkflowUntilEndAsync(this IServiceProvider services, IDictionary? input = default) where TWorkflow : IWorkflow { var workflowDefinitionId = typeof(TWorkflow).Name; return await services.RunWorkflowUntilEndAsync(workflowDefinitionId, input); } /// /// Runs the specified activity. /// /// The service provider. /// The activity to run. /// An optional cancellation token. /// The result of running the activity. public static async Task RunActivityAsync(this IServiceProvider services, IActivity activity, CancellationToken cancellationToken = default) { await services.PopulateRegistriesAsync(); var workflowRunner = services.GetRequiredService(); var result = await workflowRunner.RunAsync(activity, cancellationToken: cancellationToken); return result; } /// /// Runs the specified activity. /// /// The service provider. /// The activity to run. /// An set of options. /// An optional cancellation token. /// The result of running the activity. public static async Task RunActivityAsync(this IServiceProvider services, IActivity activity, RunWorkflowOptions options, CancellationToken cancellationToken = default) { var workflowRunner = services.GetRequiredService(); var result = await workflowRunner.RunAsync(activity, options, cancellationToken); return result; } /// /// Retrieves a workflow definition by its ID. /// /// The service provider. /// The definition ID of the workflow definition. /// Options to specify the version of the workflow definition to retrieve. /// A cancellation token to cancel the operation. /// The retrieved workflow definition. public static async Task GetWorkflowDefinitionAsync(this IServiceProvider services, string workflowDefinitionId, VersionOptions versionOptions, CancellationToken cancellationToken = default) { var workflowDefinitionService = services.GetRequiredService(); var workflowDefinition = await workflowDefinitionService.FindAsync(workflowDefinitionId, versionOptions); return workflowDefinition!; } }