< 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
90%
Covered lines: 101
Uncovered lines: 10
Coverable lines: 111
Total lines: 275
Line coverage: 90.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.WorkflowDefinitionActivity;
 18using Elsa.Workflows.Management.Contracts;
 19using Elsa.Workflows.Management.Entities;
 20using Elsa.Workflows.Management.Handlers.Notifications;
 21using Elsa.Workflows.Management.Mappers;
 22using Elsa.Workflows.Management.Materializers;
 23using Elsa.Workflows.Management.Models;
 24using Elsa.Workflows.Management.Options;
 25using Elsa.Workflows.Management.Providers;
 26using Elsa.Workflows.Management.Services;
 27using Elsa.Workflows.Management.Stores;
 28using Elsa.Workflows.Serialization.Serializers;
 29using JetBrains.Annotations;
 30using Microsoft.Extensions.DependencyInjection;
 31using Microsoft.Extensions.DependencyInjection.Extensions;
 32
 33namespace Elsa.Workflows.Management.Features;
 34
 35/// <summary>
 36/// Installs and configures the workflow management feature.
 37/// </summary>
 38[DependsOn(typeof(StringCompressionFeature))]
 39[DependsOn(typeof(MediatorFeature))]
 40[DependsOn(typeof(MemoryCacheFeature))]
 41[DependsOn(typeof(SystemClockFeature))]
 42[DependsOn(typeof(WorkflowsFeature))]
 43[DependsOn(typeof(WorkflowDefinitionsFeature))]
 44[DependsOn(typeof(WorkflowInstancesFeature))]
 45[UsedImplicitly]
 146public class WorkflowManagementFeature(IModule module) : FeatureBase(module)
 47{
 48    private const string PrimitivesCategory = "Primitives";
 49    private const string LookupsCategory = "Lookups";
 50    private const string DynamicCategory = "Dynamic";
 51    private const string DataCategory = "Data";
 52    private const string SystemCategory = "System";
 53
 32154    private Func<IServiceProvider, IWorkflowDefinitionPublisher> _workflowDefinitionPublisher = sp => ActivatorUtilities
 32155    private Func<IServiceProvider, IWorkflowReferenceQuery> _workflowReferenceQuery = sp => ActivatorUtilities.CreateIns
 56
 257    private string CompressionAlgorithm { get; set; } = nameof(None);
 358    private LogPersistenceMode LogPersistenceMode { get; set; } = LogPersistenceMode.Include;
 259    private bool IsReadOnlyMode { get; set; }
 60
 61    /// <summary>
 62    /// A set of activity types to make available to the system.
 63    /// </summary>
 2364    public HashSet<Type> ActivityTypes { get; } = [];
 65
 66    /// <summary>
 67    /// A set of variable types to make available to the system.
 68    /// </summary>
 269    public HashSet<VariableDescriptor> VariableDescriptors { get; } =
 170    [
 171        new(typeof(object), PrimitivesCategory, "The root class for all object in the CLR System."),
 172        new(typeof(string), PrimitivesCategory, "Represents a static string of characters."),
 173        new(typeof(bool), PrimitivesCategory, "Represents a true or false value."),
 174        new(typeof(int), PrimitivesCategory, "A 32 bit integer."),
 175        new(typeof(long), PrimitivesCategory, "A 64 bit integer."),
 176        new(typeof(float), PrimitivesCategory, "A 32 bit floating point number."),
 177        new(typeof(double), PrimitivesCategory, "A 64 bit floating point number."),
 178        new(typeof(decimal), PrimitivesCategory, "A decimal number."),
 179        new(typeof(Guid), PrimitivesCategory, "Represents a Globally Unique Identifier."),
 180        new(typeof(DateTime), PrimitivesCategory, "A value type that represents a date and time."),
 181        new(typeof(DateTimeOffset), PrimitivesCategory, "A value type that consists of a DateTime and a time zone offset
 182        new(typeof(TimeSpan), PrimitivesCategory, "Represents a duration of time."),
 183        new(typeof(IDictionary<string, string>), LookupsCategory, "A dictionary with string key and values."),
 184        new(typeof(IDictionary<string, object>), LookupsCategory, "A dictionary with string key and object values."),
 185        new(typeof(ExpandoObject), DynamicCategory, "A dictionary that can be typed as dynamic to access members using d
 186        new(typeof(JsonElement), DynamicCategory, "A JSON element for reading a JSON structure."),
 187        new(typeof(JsonNode), DynamicCategory, "A JSON node for reading and writing a JSON structure."),
 188        new(typeof(JsonObject), DynamicCategory, "A JSON object for reading and writing a JSON structure."),
 189        new(typeof(byte[]), DataCategory, "A byte array."),
 190        new(typeof(Stream), DataCategory, "A stream."),
 191        new(typeof(LogPersistenceMode), SystemCategory, "A LogPersistenceMode enum value.")
 192    ];
 93
 94    /// <summary>
 95    /// Adds the specified activity type to the system.
 96    /// </summary>
 1197    public WorkflowManagementFeature AddActivity<T>() where T : IActivity => AddActivity(typeof(T));
 98
 99    /// <summary>
 100    /// Adds the specified activity type to the system.
 101    /// </summary>
 102    public WorkflowManagementFeature AddActivity(Type activityType)
 103    {
 11104        ActivityTypes.Add(activityType);
 11105        return this;
 106    }
 107
 108    /// <summary>
 109    /// Adds all types implementing <see cref="IActivity"/> to the system.
 110    /// </summary>
 111    public WorkflowManagementFeature AddActivitiesFrom<TMarker>()
 112    {
 9113        var activityTypes = typeof(TMarker).Assembly.GetExportedTypes()
 1278114            .Where(x => typeof(IActivity).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, IsGeneric
 9115            .ToList();
 9116        return AddActivities(activityTypes);
 117    }
 118
 119    /// <summary>
 120    /// Adds the specified activity types to the system.
 121    /// </summary>
 122    public WorkflowManagementFeature AddActivities(IEnumerable<Type> activityTypes)
 123    {
 9124        ActivityTypes.AddRange(activityTypes);
 9125        return this;
 126    }
 127
 128    /// <summary>
 129    /// Removes the specified activity type from the system.
 130    /// </summary>
 1131    public WorkflowManagementFeature RemoveActivity<T>() where T : IActivity => RemoveActivity(typeof(T));
 132
 133    /// <summary>
 134    /// Adds the specified activity type to the system.
 135    /// </summary>
 136    public WorkflowManagementFeature RemoveActivity(Type activityType)
 137    {
 1138        ActivityTypes.Remove(activityType);
 1139        return this;
 140    }
 141
 142    /// <summary>
 143    /// Adds the specified variable type to the system.
 144    /// </summary>
 0145    public WorkflowManagementFeature AddVariableType<T>(string category) => AddVariableType(typeof(T), category);
 146
 147    /// <summary>
 148    /// Adds the specified variable type to the system.
 149    /// </summary>
 0150    public WorkflowManagementFeature AddVariableType(Type type, string category) => AddVariableTypes([type], category);
 151
 152    /// <summary>
 153    /// Adds the specified variable types to the system.
 154    /// </summary>
 155    public WorkflowManagementFeature AddVariableTypes(IEnumerable<Type> types, string category) =>
 9156        AddVariableTypes(types.Select(x => new VariableDescriptor(x, category, x.GetCustomAttribute<DescriptionAttribute
 157
 158    /// <summary>
 159    /// Adds the specified variable types to the system.
 160    /// </summary>
 161    public WorkflowManagementFeature AddVariableTypes(IEnumerable<VariableDescriptor> descriptors)
 162    {
 1163        VariableDescriptors.AddRange(descriptors);
 1164        return this;
 165    }
 166
 167    /// <summary>
 168    /// Sets the compression algorithm to use for compressing workflow state.
 169    /// </summary>
 170    public WorkflowManagementFeature SetCompressionAlgorithm(string algorithm)
 171    {
 0172        CompressionAlgorithm = algorithm;
 0173        return this;
 174    }
 175
 176    /// <summary>
 177    /// Set the default Log Persistence mode to use for worflow state (default is Include)
 178    /// </summary>
 179    /// <param name="logPersistenceMode">The mode persistence value</param>
 180    public WorkflowManagementFeature SetDefaultLogPersistenceMode(LogPersistenceMode logPersistenceMode)
 181    {
 1182        LogPersistenceMode = logPersistenceMode;
 1183        return this;
 184    }
 185
 186    /// <summary>
 187    /// Enables or disables read-only mode for resources such as workflow definitions.
 188    /// </summary>
 189    /// <returns></returns>
 190    public WorkflowManagementFeature UseReadOnlyMode(bool enabled)
 191    {
 1192        IsReadOnlyMode = enabled;
 1193        return this;
 194    }
 195
 196    public WorkflowManagementFeature UseWorkflowDefinitionPublisher(Func<IServiceProvider, IWorkflowDefinitionPublisher>
 197    {
 0198        _workflowDefinitionPublisher = workflowDefinitionPublisher;
 0199        return this;
 200    }
 201
 202    public WorkflowManagementFeature UseWorkflowReferenceFinder<T>() where T : class, IWorkflowReferenceQuery
 203    {
 0204        Services.TryAddScoped<T>();
 0205        return UseWorkflowReferenceFinder(sp => sp.GetRequiredService<T>());
 206    }
 207
 208    public WorkflowManagementFeature UseWorkflowReferenceFinder(Func<IServiceProvider, IWorkflowReferenceQuery> workflow
 209    {
 0210        _workflowReferenceQuery = workflowReferenceFinder;
 0211        return this;
 212    }
 213
 214    /// <inheritdoc />
 215    [RequiresUnreferencedCode("The assembly containing the specified marker type will be scanned for activity types.")]
 216    public override void Configure()
 217    {
 1218        AddActivitiesFrom<WorkflowManagementFeature>();
 1219    }
 220
 221    /// <inheritdoc />
 222    public override void Apply()
 223    {
 1224        Services
 1225            .AddMemoryStore<WorkflowDefinition, MemoryWorkflowDefinitionStore>()
 1226            .AddMemoryStore<WorkflowInstance, MemoryWorkflowInstanceStore>()
 1227            .AddActivityProvider<TypedActivityProvider>()
 1228            .AddActivityProvider<WorkflowDefinitionActivityProvider>()
 1229            .AddScoped<WorkflowDefinitionActivityDescriptorFactory>()
 1230            .AddScoped<WorkflowDefinitionActivityProvider>()
 1231            .AddScoped<IWorkflowDefinitionActivityRegistryUpdater, WorkflowDefinitionActivityRegistryUpdater>()
 1232            .AddScoped<IWorkflowDefinitionService, WorkflowDefinitionService>()
 1233            .AddScoped<IWorkflowSerializer, WorkflowSerializer>()
 1234            .AddScoped<IWorkflowValidator, WorkflowValidator>()
 1235            .AddScoped(_workflowReferenceQuery)
 1236            .AddScoped(_workflowDefinitionPublisher)
 1237            .AddScoped<IWorkflowDefinitionImporter, WorkflowDefinitionImporter>()
 1238            .AddScoped<IWorkflowDefinitionManager, WorkflowDefinitionManager>()
 1239            .AddScoped<IWorkflowInstanceManager, WorkflowInstanceManager>()
 1240            .AddScoped<IWorkflowReferenceUpdater, WorkflowReferenceUpdater>()
 1241            .AddScoped<IActivityRegistryPopulator, ActivityRegistryPopulator>()
 1242            .AddSingleton<IExpressionDescriptorRegistry, ExpressionDescriptorRegistry>()
 1243            .AddSingleton<IExpressionDescriptorProvider, DefaultExpressionDescriptorProvider>()
 1244            .AddSerializationOptionsConfigurator<SerializationOptionsConfigurator>()
 1245            .AddScoped<IWorkflowMaterializer, TypedWorkflowMaterializer>()
 1246            .AddScoped<IWorkflowMaterializer, ClrWorkflowMaterializer>()
 1247            .AddScoped<IWorkflowMaterializer, JsonWorkflowMaterializer>()
 1248            .AddScoped<IActivityResolver, WorkflowDefinitionActivityResolver>()
 1249            .AddScoped<IWorkflowInstanceVariableManager, WorkflowInstanceVariableManager>()
 1250            .AddScoped<WorkflowDefinitionMapper>()
 1251            .AddSingleton<VariableDefinitionMapper>()
 1252            .AddSingleton<WorkflowStateMapper>()
 1253            ;
 254
 1255        Services
 1256            .AddNotificationHandler<DeleteWorkflowInstances>()
 1257            .AddNotificationHandler<RefreshActivityRegistry>()
 1258            .AddNotificationHandler<UpdateConsumingWorkflows>()
 1259            .AddNotificationHandler<ValidateWorkflow>()
 1260            ;
 261
 1262        Services.Configure<ManagementOptions>(options =>
 1263        {
 112264            foreach (var activityType in ActivityTypes.Distinct())
 55265                options.ActivityTypes.Add(activityType);
 1266
 89267            foreach (var descriptor in VariableDescriptors.DistinctBy(x => x.Type))
 29268                options.VariableDescriptors.Add(descriptor);
 1269
 1270            options.CompressionAlgorithm = CompressionAlgorithm;
 1271            options.LogPersistenceMode = LogPersistenceMode;
 1272            options.IsReadOnlyMode = IsReadOnlyMode;
 2273        });
 1274    }
 275}