using Elsa.Common.Models; using Elsa.Workflows; using Elsa.Workflows.Contracts; using Elsa.Workflows.Management; 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.Parameters; 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. /// An optional set of options to specify the version of the workflow definition to retrieve. /// The workflow state. public static async Task RunWorkflowUntilEndAsync(this IServiceProvider services, string workflowDefinitionId, IDictionary? input = default, VersionOptions? versionOptions = default) { var workflowDefinitionService = services.GetRequiredService(); var workflowGraph = await workflowDefinitionService.FindWorkflowGraphAsync(workflowDefinitionId, versionOptions ?? VersionOptions.Published); var workflowRuntime = services.GetRequiredService(); var workflowClient = await workflowRuntime.CreateClientAsync(); var response = await workflowClient.CreateAndRunInstanceAsync(new CreateAndRunWorkflowInstanceRequest { WorkflowDefinitionHandle = WorkflowDefinitionHandle.ByDefinitionVersionId(workflowGraph!.Workflow.Identity.Id), Input = input }); var bookmarkStore = services.GetRequiredService(); // Continue resuming the workflow for as long as there are bookmarks to resume and the workflow is not Finished. while (response.Status != WorkflowStatus.Finished) { var bookmarks = (await bookmarkStore.FindManyAsync(new BookmarkFilter { WorkflowInstanceId = response.WorkflowInstanceId })).ToList(); if (!bookmarks.Any()) break; foreach (var bookmark in bookmarks) { var runRequest = new RunWorkflowInstanceRequest { BookmarkId = bookmark.Id }; response = await workflowClient.RunInstanceAsync(runRequest); } } // Return the workflow state. return await workflowClient.ExportStateAsync(); } /// /// 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.FindWorkflowDefinitionAsync(workflowDefinitionId, versionOptions); return workflowDefinition!; } }