< 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
88%
Covered lines: 109
Uncovered lines: 14
Coverable lines: 123
Total lines: 315
Line coverage: 88.6%
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]
 347public 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
 40855    private Func<IServiceProvider, IWorkflowDefinitionPublisher> _workflowDefinitionPublisher = sp => ActivatorUtilities
 41556    private Func<IServiceProvider, IWorkflowReferenceQuery> _workflowReferenceQuery = sp => ActivatorUtilities.CreateIns
 57
 658    private string CompressionAlgorithm { get; set; } = nameof(None);
 959    private LogPersistenceMode LogPersistenceMode { get; set; } = LogPersistenceMode.Include;
 660    private bool IsReadOnlyMode { get; set; }
 61
 62    /// <summary>
 63    /// A set of activity types to make available to the system.
 64    /// </summary>
 7565    public HashSet<Type> ActivityTypes { get; } = [];
 66
 67    /// <summary>
 68    /// A set of variable types to make available to the system.
 69    /// </summary>
 670    public HashSet<VariableDescriptor> VariableDescriptors { get; } =
 371    [
 372        new(typeof(object), PrimitivesCategory, "The root class for all object in the CLR System."),
 373        new(typeof(string), PrimitivesCategory, "Represents a static string of characters."),
 374        new(typeof(bool), PrimitivesCategory, "Represents a true or false value."),
 375        new(typeof(int), PrimitivesCategory, "A 32 bit integer."),
 376        new(typeof(long), PrimitivesCategory, "A 64 bit integer."),
 377        new(typeof(float), PrimitivesCategory, "A 32 bit floating point number."),
 378        new(typeof(double), PrimitivesCategory, "A 64 bit floating point number."),
 379        new(typeof(decimal), PrimitivesCategory, "A decimal number."),
 380        new(typeof(Guid), PrimitivesCategory, "Represents a Globally Unique Identifier."),
 381        new(typeof(DateTime), PrimitivesCategory, "A value type that represents a date and time."),
 382        new(typeof(DateTimeOffset), PrimitivesCategory, "A value type that consists of a DateTime and a time zone offset
 383        new(typeof(TimeSpan), PrimitivesCategory, "Represents a duration of time."),
 384        new(typeof(IDictionary<string, string>), LookupsCategory, "A dictionary with string key and values."),
 385        new(typeof(IDictionary<string, object>), LookupsCategory, "A dictionary with string key and object values."),
 386        new(typeof(ExpandoObject), DynamicCategory, "A dictionary that can be typed as dynamic to access members using d
 387        new(typeof(JsonElement), DynamicCategory, "A JSON element for reading a JSON structure."),
 388        new(typeof(JsonNode), DynamicCategory, "A JSON node for reading and writing a JSON structure."),
 389        new(typeof(JsonObject), DynamicCategory, "A JSON object for reading and writing a JSON structure."),
 390        new(typeof(byte[]), DataCategory, "A byte array."),
 391        new(typeof(Stream), DataCategory, "A stream."),
 392        new(typeof(LogPersistenceMode), SystemCategory, "A LogPersistenceMode enum value.")
 393    ];
 94
 95    /// <summary>
 96    /// Adds the specified activity type to the system.
 97    /// </summary>
 3998    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    {
 39105        ActivityTypes.Add(activityType);
 39106        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    {
 27114        var activityTypes = typeof(TMarker).Assembly.GetExportedTypes()
 4068115            .Where(x => typeof(IActivity).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, IsGeneric
 27116            .ToList();
 27117        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    {
 27125        ActivityTypes.AddRange(activityTypes);
 27126        return this;
 127    }
 128
 129    /// <summary>
 130    /// Removes the specified activity type from the system.
 131    /// </summary>
 3132    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    {
 3139        ActivityTypes.Remove(activityType);
 3140        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    {
 12150        Module.Services.Configure<HostMethodActivitiesOptions>(options => options.AddType<T>(key));
 6151        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) =>
 27179        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    {
 3186        VariableDescriptors.AddRange(descriptors);
 3187        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    {
 3205        LogPersistenceMode = logPersistenceMode;
 3206        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    {
 3215        IsReadOnlyMode = enabled;
 3216        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    /// <summary>
 238    /// Configures the workflow reference graph builder options.
 239    /// </summary>
 240    /// <param name="configure">A delegate to configure the options.</param>
 241    public WorkflowManagementFeature ConfigureWorkflowReferenceGraph(Action<WorkflowReferenceGraphOptions> configure)
 242    {
 0243        Services.Configure(configure);
 0244        return this;
 245    }
 246
 247    /// <inheritdoc />
 248    [RequiresUnreferencedCode("The assembly containing the specified marker type will be scanned for activity types.")]
 249    public override void Configure()
 250    {
 3251        AddActivitiesFrom<WorkflowManagementFeature>();
 3252    }
 253
 254    /// <inheritdoc />
 255    public override void Apply()
 256    {
 3257        Services
 3258             .AddMemoryStore<WorkflowDefinition, MemoryWorkflowDefinitionStore>()
 3259             .AddMemoryStore<WorkflowInstance, MemoryWorkflowInstanceStore>()
 3260             .AddActivityProvider<TypedActivityProvider>()
 3261             .AddActivityProvider<WorkflowDefinitionActivityProvider>()
 3262             .AddActivityProvider<HostMethodActivityProvider>()
 3263             .AddScoped<IHostMethodActivityDescriber, HostMethodActivityDescriber>()
 3264             .AddScoped<IHostMethodParameterValueProvider, DefaultHostMethodParameterValueProvider>()
 3265             .AddScoped<WorkflowDefinitionActivityDescriptorFactory>()
 3266             .AddScoped<WorkflowDefinitionActivityProvider>()
 3267             .AddScoped<IWorkflowDefinitionActivityRegistryUpdater, WorkflowDefinitionActivityRegistryUpdater>()
 3268             .AddScoped<IWorkflowDefinitionService, WorkflowDefinitionService>()
 3269             .AddScoped<IWorkflowSerializer, WorkflowSerializer>()
 3270             .AddScoped<IWorkflowValidator, WorkflowValidator>()
 3271             .AddScoped(_workflowReferenceQuery)
 3272             .AddScoped<IWorkflowReferenceGraphBuilder, WorkflowReferenceGraphBuilder>()
 3273             .AddScoped(_workflowDefinitionPublisher)
 3274             .AddScoped<IWorkflowDefinitionImporter, WorkflowDefinitionImporter>()
 3275             .AddScoped<IWorkflowDefinitionManager, WorkflowDefinitionManager>()
 3276             .AddScoped<IWorkflowInstanceManager, WorkflowInstanceManager>()
 3277             .AddScoped<IWorkflowReferenceUpdater, WorkflowReferenceUpdater>()
 3278             .AddScoped<IActivityRegistryPopulator, ActivityRegistryPopulator>()
 3279             .AddSingleton<IExpressionDescriptorRegistry, ExpressionDescriptorRegistry>()
 3280             .AddSingleton<IExpressionDescriptorProvider, DefaultExpressionDescriptorProvider>()
 3281             .AddSerializationOptionsConfigurator<SerializationOptionsConfigurator>()
 3282             .AddScoped<IWorkflowMaterializer, TypedWorkflowMaterializer>()
 3283             .AddScoped<IWorkflowMaterializer, ClrWorkflowMaterializer>()
 3284             .AddScoped<IWorkflowMaterializer, JsonWorkflowMaterializer>()
 3285             .AddScoped<IActivityResolver, WorkflowDefinitionActivityResolver>()
 3286             .AddScoped<IWorkflowInstanceVariableManager, WorkflowInstanceVariableManager>()
 3287             .AddScoped<WorkflowDefinitionMapper>()
 3288             .AddSingleton<VariableDefinitionMapper>()
 3289             .AddSingleton<WorkflowStateMapper>()
 3290             ;
 291
 3292        Services
 3293            .AddNotificationHandler<DeleteWorkflowInstances>()
 3294            .AddNotificationHandler<RefreshActivityRegistry>()
 3295            .AddNotificationHandler<UpdateConsumingWorkflows>()
 3296            .AddNotificationHandler<ValidateWorkflow>()
 3297            ;
 298
 3299        Services.Configure<ManagementOptions>(options =>
 3300        {
 342301            foreach (var activityType in ActivityTypes.Distinct())
 168302                options.ActivityTypes.Add(activityType);
 3303
 267304            foreach (var descriptor in VariableDescriptors.DistinctBy(x => x.Type))
 87305                options.VariableDescriptors.Add(descriptor);
 3306
 3307            options.CompressionAlgorithm = CompressionAlgorithm;
 3308            options.LogPersistenceMode = LogPersistenceMode;
 3309            options.IsReadOnlyMode = IsReadOnlyMode;
 6310        });
 311
 6312        Services.Configure<HostMethodActivitiesOptions>(_ => { });
 6313        Services.Configure<WorkflowReferenceGraphOptions>(_ => { });
 3314    }
 315}