< Summary

Information
Class: Elsa.Workflows.Management.Features.WorkflowManagementFeature
Assembly: Elsa.Workflows.Management
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs
Line coverage
89%
Covered lines: 107
Uncovered lines: 12
Coverable lines: 119
Total lines: 303
Line coverage: 89.9%
Branch coverage
78%
Covered branches: 11
Total branches: 14
Branch coverage: 78.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs

#LineLine coverage
 1using System.ComponentModel;
 2using System.Diagnostics.CodeAnalysis;
 3using System.Dynamic;
 4using System.Reflection;
 5using System.Text.Json;
 6using System.Text.Json.Nodes;
 7using Elsa.Caching.Features;
 8using Elsa.Common.Codecs;
 9using Elsa.Common.Features;
 10using Elsa.Expressions.Contracts;
 11using Elsa.Extensions;
 12using Elsa.Features.Abstractions;
 13using Elsa.Features.Attributes;
 14using Elsa.Features.Services;
 15using Elsa.Workflows.Features;
 16using Elsa.Workflows.LogPersistence;
 17using Elsa.Workflows.Management.Activities.HostMethod;
 18using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity;
 19using Elsa.Workflows.Management.Contracts;
 20using Elsa.Workflows.Management.Entities;
 21using Elsa.Workflows.Management.Handlers.Notifications;
 22using Elsa.Workflows.Management.Mappers;
 23using Elsa.Workflows.Management.Materializers;
 24using Elsa.Workflows.Management.Models;
 25using Elsa.Workflows.Management.Options;
 26using Elsa.Workflows.Management.Providers;
 27using Elsa.Workflows.Management.Services;
 28using Elsa.Workflows.Management.Stores;
 29using Elsa.Workflows.Serialization.Serializers;
 30using JetBrains.Annotations;
 31using Microsoft.Extensions.DependencyInjection;
 32using Microsoft.Extensions.DependencyInjection.Extensions;
 33
 34namespace Elsa.Workflows.Management.Features;
 35
 36/// <summary>
 37/// Installs and configures the workflow management feature.
 38/// </summary>
 39[DependsOn(typeof(StringCompressionFeature))]
 40[DependsOn(typeof(MediatorFeature))]
 41[DependsOn(typeof(MemoryCacheFeature))]
 42[DependsOn(typeof(SystemClockFeature))]
 43[DependsOn(typeof(WorkflowsFeature))]
 44[DependsOn(typeof(WorkflowDefinitionsFeature))]
 45[DependsOn(typeof(WorkflowInstancesFeature))]
 46[UsedImplicitly]
 747public class WorkflowManagementFeature(IModule module) : FeatureBase(module)
 48{
 49    private const string PrimitivesCategory = "Primitives";
 50    private const string LookupsCategory = "Lookups";
 51    private const string DynamicCategory = "Dynamic";
 52    private const string DataCategory = "Data";
 53    private const string SystemCategory = "System";
 54
 43755    private Func<IServiceProvider, IWorkflowDefinitionPublisher> _workflowDefinitionPublisher = sp => ActivatorUtilities
 43756    private Func<IServiceProvider, IWorkflowReferenceQuery> _workflowReferenceQuery = sp => ActivatorUtilities.CreateIns
 57
 1458    private string CompressionAlgorithm { get; set; } = nameof(None);
 2159    private LogPersistenceMode LogPersistenceMode { get; set; } = LogPersistenceMode.Include;
 1460    private bool IsReadOnlyMode { get; set; }
 61
 62    /// <summary>
 63    /// A set of activity types to make available to the system.
 64    /// </summary>
 17565    public HashSet<Type> ActivityTypes { get; } = [];
 66
 67    /// <summary>
 68    /// A set of variable types to make available to the system.
 69    /// </summary>
 1470    public HashSet<VariableDescriptor> VariableDescriptors { get; } =
 771    [
 772        new(typeof(object), PrimitivesCategory, "The root class for all object in the CLR System."),
 773        new(typeof(string), PrimitivesCategory, "Represents a static string of characters."),
 774        new(typeof(bool), PrimitivesCategory, "Represents a true or false value."),
 775        new(typeof(int), PrimitivesCategory, "A 32 bit integer."),
 776        new(typeof(long), PrimitivesCategory, "A 64 bit integer."),
 777        new(typeof(float), PrimitivesCategory, "A 32 bit floating point number."),
 778        new(typeof(double), PrimitivesCategory, "A 64 bit floating point number."),
 779        new(typeof(decimal), PrimitivesCategory, "A decimal number."),
 780        new(typeof(Guid), PrimitivesCategory, "Represents a Globally Unique Identifier."),
 781        new(typeof(DateTime), PrimitivesCategory, "A value type that represents a date and time."),
 782        new(typeof(DateTimeOffset), PrimitivesCategory, "A value type that consists of a DateTime and a time zone offset
 783        new(typeof(TimeSpan), PrimitivesCategory, "Represents a duration of time."),
 784        new(typeof(IDictionary<string, string>), LookupsCategory, "A dictionary with string key and values."),
 785        new(typeof(IDictionary<string, object>), LookupsCategory, "A dictionary with string key and object values."),
 786        new(typeof(ExpandoObject), DynamicCategory, "A dictionary that can be typed as dynamic to access members using d
 787        new(typeof(JsonElement), DynamicCategory, "A JSON element for reading a JSON structure."),
 788        new(typeof(JsonNode), DynamicCategory, "A JSON node for reading and writing a JSON structure."),
 789        new(typeof(JsonObject), DynamicCategory, "A JSON object for reading and writing a JSON structure."),
 790        new(typeof(byte[]), DataCategory, "A byte array."),
 791        new(typeof(Stream), DataCategory, "A stream."),
 792        new(typeof(LogPersistenceMode), SystemCategory, "A LogPersistenceMode enum value.")
 793    ];
 94
 95    /// <summary>
 96    /// Adds the specified activity type to the system.
 97    /// </summary>
 9198    public WorkflowManagementFeature AddActivity<T>() where T : IActivity => AddActivity(typeof(T));
 99
 100    /// <summary>
 101    /// Adds the specified activity type to the system.
 102    /// </summary>
 103    public WorkflowManagementFeature AddActivity(Type activityType)
 104    {
 91105        ActivityTypes.Add(activityType);
 91106        return this;
 107    }
 108
 109    /// <summary>
 110    /// Adds all types implementing <see cref="IActivity"/> to the system.
 111    /// </summary>
 112    public WorkflowManagementFeature AddActivitiesFrom<TMarker>()
 113    {
 63114        var activityTypes = typeof(TMarker).Assembly.GetExportedTypes()
 9380115            .Where(x => typeof(IActivity).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, IsGeneric
 63116            .ToList();
 63117        return AddActivities(activityTypes);
 118    }
 119
 120    /// <summary>
 121    /// Adds the specified activity types to the system.
 122    /// </summary>
 123    public WorkflowManagementFeature AddActivities(IEnumerable<Type> activityTypes)
 124    {
 63125        ActivityTypes.AddRange(activityTypes);
 63126        return this;
 127    }
 128
 129    /// <summary>
 130    /// Removes the specified activity type from the system.
 131    /// </summary>
 7132    public WorkflowManagementFeature RemoveActivity<T>() where T : IActivity => RemoveActivity(typeof(T));
 133
 134    /// <summary>
 135    /// Adds the specified activity type to the system.
 136    /// </summary>
 137    public WorkflowManagementFeature RemoveActivity(Type activityType)
 138    {
 7139        ActivityTypes.Remove(activityType);
 7140        return this;
 141    }
 142
 143    /// <summary>
 144    /// Configures the system to add a specific activity host type to the workflow management feature.
 145    /// </summary>
 146    /// <typeparam name="T">The type of the activity host to be added.</typeparam>
 147    /// <param name="key">An optional unique key to associate with the activity host type.</param>
 148    public WorkflowManagementFeature AddActivityHost<T>(string? key = null) where T : class
 149    {
 28150        Module.Services.Configure<HostMethodActivitiesOptions>(options => options.AddType<T>(key));
 14151        return this;
 152    }
 153
 154    /// <summary>
 155    /// Configures the system to add a specific activity host type to the workflow management feature.
 156    /// </summary>
 157    /// <param name="hostType">The type of the activity host to be added.</param>
 158    /// <param name="key">An optional unique key to associate with the activity host type.</param>
 159    public WorkflowManagementFeature AddActivityHost(Type hostType, string? key = null)
 160    {
 0161        Module.Services.Configure<HostMethodActivitiesOptions>(options => options.AddType(hostType, key));
 0162        return this;
 163    }
 164
 165    /// <summary>
 166    /// Adds the specified variable type to the system.
 167    /// </summary>
 0168    public WorkflowManagementFeature AddVariableType<T>(string category) => AddVariableType(typeof(T), category);
 169
 170    /// <summary>
 171    /// Adds the specified variable type to the system.
 172    /// </summary>
 0173    public WorkflowManagementFeature AddVariableType(Type type, string category) => AddVariableTypes([type], category);
 174
 175    /// <summary>
 176    /// Adds the specified variable types to the system.
 177    /// </summary>
 178    public WorkflowManagementFeature AddVariableTypes(IEnumerable<Type> types, string category) =>
 63179        AddVariableTypes(types.Select(x => new VariableDescriptor(x, category, x.GetCustomAttribute<DescriptionAttribute
 180
 181    /// <summary>
 182    /// Adds the specified variable types to the system.
 183    /// </summary>
 184    public WorkflowManagementFeature AddVariableTypes(IEnumerable<VariableDescriptor> descriptors)
 185    {
 7186        VariableDescriptors.AddRange(descriptors);
 7187        return this;
 188    }
 189
 190    /// <summary>
 191    /// Sets the compression algorithm to use for compressing workflow state.
 192    /// </summary>
 193    public WorkflowManagementFeature SetCompressionAlgorithm(string algorithm)
 194    {
 0195        CompressionAlgorithm = algorithm;
 0196        return this;
 197    }
 198
 199    /// <summary>
 200    /// Set the default Log Persistence mode to use for worflow state (default is Include)
 201    /// </summary>
 202    /// <param name="logPersistenceMode">The mode persistence value</param>
 203    public WorkflowManagementFeature SetDefaultLogPersistenceMode(LogPersistenceMode logPersistenceMode)
 204    {
 7205        LogPersistenceMode = logPersistenceMode;
 7206        return this;
 207    }
 208
 209    /// <summary>
 210    /// Enables or disables read-only mode for resources such as workflow definitions.
 211    /// </summary>
 212    /// <returns></returns>
 213    public WorkflowManagementFeature UseReadOnlyMode(bool enabled)
 214    {
 7215        IsReadOnlyMode = enabled;
 7216        return this;
 217    }
 218
 219    public WorkflowManagementFeature UseWorkflowDefinitionPublisher(Func<IServiceProvider, IWorkflowDefinitionPublisher>
 220    {
 0221        _workflowDefinitionPublisher = workflowDefinitionPublisher;
 0222        return this;
 223    }
 224
 225    public WorkflowManagementFeature UseWorkflowReferenceFinder<T>() where T : class, IWorkflowReferenceQuery
 226    {
 0227        Services.TryAddScoped<T>();
 0228        return UseWorkflowReferenceFinder(sp => sp.GetRequiredService<T>());
 229    }
 230
 231    public WorkflowManagementFeature UseWorkflowReferenceFinder(Func<IServiceProvider, IWorkflowReferenceQuery> workflow
 232    {
 0233        _workflowReferenceQuery = workflowReferenceFinder;
 0234        return this;
 235    }
 236
 237    /// <inheritdoc />
 238    [RequiresUnreferencedCode("The assembly containing the specified marker type will be scanned for activity types.")]
 239    public override void Configure()
 240    {
 7241        AddActivitiesFrom<WorkflowManagementFeature>();
 7242    }
 243
 244    /// <inheritdoc />
 245    public override void Apply()
 246    {
 7247        Services
 7248             .AddMemoryStore<WorkflowDefinition, MemoryWorkflowDefinitionStore>()
 7249             .AddMemoryStore<WorkflowInstance, MemoryWorkflowInstanceStore>()
 7250             .AddActivityProvider<TypedActivityProvider>()
 7251             .AddActivityProvider<WorkflowDefinitionActivityProvider>()
 7252             .AddActivityProvider<HostMethodActivityProvider>()
 7253             .AddScoped<IHostMethodActivityDescriber, HostMethodActivityDescriber>()
 7254             .AddScoped<IHostMethodParameterValueProvider, DefaultHostMethodParameterValueProvider>()
 7255             .AddScoped<WorkflowDefinitionActivityDescriptorFactory>()
 7256             .AddScoped<WorkflowDefinitionActivityProvider>()
 7257             .AddScoped<IWorkflowDefinitionActivityRegistryUpdater, WorkflowDefinitionActivityRegistryUpdater>()
 7258             .AddScoped<IWorkflowDefinitionService, WorkflowDefinitionService>()
 7259             .AddScoped<IWorkflowSerializer, WorkflowSerializer>()
 7260             .AddScoped<IWorkflowValidator, WorkflowValidator>()
 7261             .AddScoped(_workflowReferenceQuery)
 7262             .AddScoped(_workflowDefinitionPublisher)
 7263             .AddScoped<IWorkflowDefinitionImporter, WorkflowDefinitionImporter>()
 7264             .AddScoped<IWorkflowDefinitionManager, WorkflowDefinitionManager>()
 7265             .AddScoped<IWorkflowInstanceManager, WorkflowInstanceManager>()
 7266             .AddScoped<IWorkflowReferenceUpdater, WorkflowReferenceUpdater>()
 7267             .AddScoped<IActivityRegistryPopulator, ActivityRegistryPopulator>()
 7268             .AddSingleton<IExpressionDescriptorRegistry, ExpressionDescriptorRegistry>()
 7269             .AddSingleton<IExpressionDescriptorProvider, DefaultExpressionDescriptorProvider>()
 7270             .AddSerializationOptionsConfigurator<SerializationOptionsConfigurator>()
 7271             .AddScoped<IWorkflowMaterializer, TypedWorkflowMaterializer>()
 7272             .AddScoped<IWorkflowMaterializer, ClrWorkflowMaterializer>()
 7273             .AddScoped<IWorkflowMaterializer, JsonWorkflowMaterializer>()
 7274             .AddScoped<IActivityResolver, WorkflowDefinitionActivityResolver>()
 7275             .AddScoped<IWorkflowInstanceVariableManager, WorkflowInstanceVariableManager>()
 7276             .AddScoped<WorkflowDefinitionMapper>()
 7277             .AddSingleton<VariableDefinitionMapper>()
 7278             .AddSingleton<WorkflowStateMapper>()
 7279             ;
 280
 7281        Services
 7282            .AddNotificationHandler<DeleteWorkflowInstances>()
 7283            .AddNotificationHandler<RefreshActivityRegistry>()
 7284            .AddNotificationHandler<UpdateConsumingWorkflows>()
 7285            .AddNotificationHandler<ValidateWorkflow>()
 7286            ;
 287
 7288        Services.Configure<ManagementOptions>(options =>
 7289        {
 798290            foreach (var activityType in ActivityTypes.Distinct())
 392291                options.ActivityTypes.Add(activityType);
 7292
 623293            foreach (var descriptor in VariableDescriptors.DistinctBy(x => x.Type))
 203294                options.VariableDescriptors.Add(descriptor);
 7295
 7296            options.CompressionAlgorithm = CompressionAlgorithm;
 7297            options.LogPersistenceMode = LogPersistenceMode;
 7298            options.IsReadOnlyMode = IsReadOnlyMode;
 14299        });
 300
 14301        Services.Configure<HostMethodActivitiesOptions>(_ => { });
 7302    }
 303}