< 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: 113
Uncovered lines: 14
Coverable lines: 127
Total lines: 320
Line coverage: 88.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.Expressions.Options;
 12using Elsa.Extensions;
 13using Elsa.Features.Abstractions;
 14using Elsa.Features.Attributes;
 15using Elsa.Features.Services;
 16using Elsa.Workflows.Features;
 17using Elsa.Workflows.LogPersistence;
 18using Elsa.Workflows.Management.Activities.HostMethod;
 19using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity;
 20using Elsa.Workflows.Management.Contracts;
 21using Elsa.Workflows.Management.Entities;
 22using Elsa.Workflows.Management.Handlers.Notifications;
 23using Elsa.Workflows.Management.Mappers;
 24using Elsa.Workflows.Management.Materializers;
 25using Elsa.Workflows.Management.Models;
 26using Elsa.Workflows.Management.Options;
 27using Elsa.Workflows.Management.Providers;
 28using Elsa.Workflows.Management.Services;
 29using Elsa.Workflows.Management.Stores;
 30using Elsa.Workflows.Serialization.Serializers;
 31using JetBrains.Annotations;
 32using Microsoft.Extensions.DependencyInjection;
 33using Microsoft.Extensions.DependencyInjection.Extensions;
 34
 35namespace Elsa.Workflows.Management.Features;
 36
 37/// <summary>
 38/// Installs and configures the workflow management feature.
 39/// </summary>
 40[DependsOn(typeof(StringCompressionFeature))]
 41[DependsOn(typeof(MediatorFeature))]
 42[DependsOn(typeof(MemoryCacheFeature))]
 43[DependsOn(typeof(SystemClockFeature))]
 44[DependsOn(typeof(WorkflowsFeature))]
 45[DependsOn(typeof(WorkflowDefinitionsFeature))]
 46[DependsOn(typeof(WorkflowInstancesFeature))]
 47[UsedImplicitly]
 348public class WorkflowManagementFeature(IModule module) : FeatureBase(module)
 49{
 50    private const string PrimitivesCategory = "Primitives";
 51    private const string LookupsCategory = "Lookups";
 52    private const string DynamicCategory = "Dynamic";
 53    private const string DataCategory = "Data";
 54    private const string SystemCategory = "System";
 55
 40256    private Func<IServiceProvider, IWorkflowDefinitionPublisher> _workflowDefinitionPublisher = sp => ActivatorUtilities
 40757    private Func<IServiceProvider, IWorkflowReferenceQuery> _workflowReferenceQuery = sp => ActivatorUtilities.CreateIns
 58
 659    private string CompressionAlgorithm { get; set; } = nameof(None);
 960    private LogPersistenceMode LogPersistenceMode { get; set; } = LogPersistenceMode.Include;
 661    private bool IsReadOnlyMode { get; set; }
 62
 63    /// <summary>
 64    /// A set of activity types to make available to the system.
 65    /// </summary>
 7566    public HashSet<Type> ActivityTypes { get; } = [];
 67
 68    /// <summary>
 69    /// A set of variable types to make available to the system.
 70    /// </summary>
 671    public HashSet<VariableDescriptor> VariableDescriptors { get; } =
 372    [
 373        new(typeof(object), PrimitivesCategory, "The root class for all object in the CLR System."),
 374        new(typeof(string), PrimitivesCategory, "Represents a static string of characters."),
 375        new(typeof(bool), PrimitivesCategory, "Represents a true or false value."),
 376        new(typeof(int), PrimitivesCategory, "A 32 bit integer."),
 377        new(typeof(long), PrimitivesCategory, "A 64 bit integer."),
 378        new(typeof(float), PrimitivesCategory, "A 32 bit floating point number."),
 379        new(typeof(double), PrimitivesCategory, "A 64 bit floating point number."),
 380        new(typeof(decimal), PrimitivesCategory, "A decimal number."),
 381        new(typeof(Guid), PrimitivesCategory, "Represents a Globally Unique Identifier."),
 382        new(typeof(DateTime), PrimitivesCategory, "A value type that represents a date and time."),
 383        new(typeof(DateTimeOffset), PrimitivesCategory, "A value type that consists of a DateTime and a time zone offset
 384        new(typeof(TimeSpan), PrimitivesCategory, "Represents a duration of time."),
 385        new(typeof(IDictionary<string, string>), LookupsCategory, "A dictionary with string key and values."),
 386        new(typeof(IDictionary<string, object>), LookupsCategory, "A dictionary with string key and object values."),
 387        new(typeof(ExpandoObject), DynamicCategory, "A dictionary that can be typed as dynamic to access members using d
 388        new(typeof(JsonElement), DynamicCategory, "A JSON element for reading a JSON structure."),
 389        new(typeof(JsonNode), DynamicCategory, "A JSON node for reading and writing a JSON structure."),
 390        new(typeof(JsonObject), DynamicCategory, "A JSON object for reading and writing a JSON structure."),
 391        new(typeof(byte[]), DataCategory, "A byte array."),
 392        new(typeof(Stream), DataCategory, "A stream."),
 393        new(typeof(LogPersistenceMode), SystemCategory, "A LogPersistenceMode enum value.")
 394    ];
 95
 96    /// <summary>
 97    /// Adds the specified activity type to the system.
 98    /// </summary>
 3999    public WorkflowManagementFeature AddActivity<T>() where T : IActivity => AddActivity(typeof(T));
 100
 101    /// <summary>
 102    /// Adds the specified activity type to the system.
 103    /// </summary>
 104    public WorkflowManagementFeature AddActivity(Type activityType)
 105    {
 39106        ActivityTypes.Add(activityType);
 39107        return this;
 108    }
 109
 110    /// <summary>
 111    /// Adds all types implementing <see cref="IActivity"/> to the system.
 112    /// </summary>
 113    public WorkflowManagementFeature AddActivitiesFrom<TMarker>()
 114    {
 27115        var activityTypes = typeof(TMarker).Assembly.GetExportedTypes()
 4401116            .Where(x => typeof(IActivity).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, IsGeneric
 27117            .ToList();
 27118        return AddActivities(activityTypes);
 119    }
 120
 121    /// <summary>
 122    /// Adds the specified activity types to the system.
 123    /// </summary>
 124    public WorkflowManagementFeature AddActivities(IEnumerable<Type> activityTypes)
 125    {
 27126        ActivityTypes.AddRange(activityTypes);
 27127        return this;
 128    }
 129
 130    /// <summary>
 131    /// Removes the specified activity type from the system.
 132    /// </summary>
 3133    public WorkflowManagementFeature RemoveActivity<T>() where T : IActivity => RemoveActivity(typeof(T));
 134
 135    /// <summary>
 136    /// Adds the specified activity type to the system.
 137    /// </summary>
 138    public WorkflowManagementFeature RemoveActivity(Type activityType)
 139    {
 3140        ActivityTypes.Remove(activityType);
 3141        return this;
 142    }
 143
 144    /// <summary>
 145    /// Configures the system to add a specific activity host type to the workflow management feature.
 146    /// </summary>
 147    /// <typeparam name="T">The type of the activity host to be added.</typeparam>
 148    /// <param name="key">An optional unique key to associate with the activity host type.</param>
 149    public WorkflowManagementFeature AddActivityHost<T>(string? key = null) where T : class
 150    {
 12151        Module.Services.Configure<HostMethodActivitiesOptions>(options => options.AddType<T>(key));
 6152        return this;
 153    }
 154
 155    /// <summary>
 156    /// Configures the system to add a specific activity host type to the workflow management feature.
 157    /// </summary>
 158    /// <param name="hostType">The type of the activity host to be added.</param>
 159    /// <param name="key">An optional unique key to associate with the activity host type.</param>
 160    public WorkflowManagementFeature AddActivityHost(Type hostType, string? key = null)
 161    {
 0162        Module.Services.Configure<HostMethodActivitiesOptions>(options => options.AddType(hostType, key));
 0163        return this;
 164    }
 165
 166    /// <summary>
 167    /// Adds the specified variable type to the system.
 168    /// </summary>
 0169    public WorkflowManagementFeature AddVariableType<T>(string category) => AddVariableType(typeof(T), category);
 170
 171    /// <summary>
 172    /// Adds the specified variable type to the system.
 173    /// </summary>
 0174    public WorkflowManagementFeature AddVariableType(Type type, string category) => AddVariableTypes([type], category);
 175
 176    /// <summary>
 177    /// Adds the specified variable types to the system.
 178    /// </summary>
 179    public WorkflowManagementFeature AddVariableTypes(IEnumerable<Type> types, string category) =>
 27180        AddVariableTypes(types.Select(x => new VariableDescriptor(x, category, x.GetCustomAttribute<DescriptionAttribute
 181
 182    /// <summary>
 183    /// Adds the specified variable types to the system.
 184    /// </summary>
 185    public WorkflowManagementFeature AddVariableTypes(IEnumerable<VariableDescriptor> descriptors)
 186    {
 3187        VariableDescriptors.AddRange(descriptors);
 3188        return this;
 189    }
 190
 191    /// <summary>
 192    /// Sets the compression algorithm to use for compressing workflow state.
 193    /// </summary>
 194    public WorkflowManagementFeature SetCompressionAlgorithm(string algorithm)
 195    {
 0196        CompressionAlgorithm = algorithm;
 0197        return this;
 198    }
 199
 200    /// <summary>
 201    /// Set the default Log Persistence mode to use for worflow state (default is Include)
 202    /// </summary>
 203    /// <param name="logPersistenceMode">The mode persistence value</param>
 204    public WorkflowManagementFeature SetDefaultLogPersistenceMode(LogPersistenceMode logPersistenceMode)
 205    {
 3206        LogPersistenceMode = logPersistenceMode;
 3207        return this;
 208    }
 209
 210    /// <summary>
 211    /// Enables or disables read-only mode for resources such as workflow definitions.
 212    /// </summary>
 213    /// <returns></returns>
 214    public WorkflowManagementFeature UseReadOnlyMode(bool enabled)
 215    {
 3216        IsReadOnlyMode = enabled;
 3217        return this;
 218    }
 219
 220    public WorkflowManagementFeature UseWorkflowDefinitionPublisher(Func<IServiceProvider, IWorkflowDefinitionPublisher>
 221    {
 0222        _workflowDefinitionPublisher = workflowDefinitionPublisher;
 0223        return this;
 224    }
 225
 226    public WorkflowManagementFeature UseWorkflowReferenceFinder<T>() where T : class, IWorkflowReferenceQuery
 227    {
 0228        Services.TryAddScoped<T>();
 0229        return UseWorkflowReferenceFinder(sp => sp.GetRequiredService<T>());
 230    }
 231
 232    public WorkflowManagementFeature UseWorkflowReferenceFinder(Func<IServiceProvider, IWorkflowReferenceQuery> workflow
 233    {
 0234        _workflowReferenceQuery = workflowReferenceFinder;
 0235        return this;
 236    }
 237
 238    /// <summary>
 239    /// Configures the workflow reference graph builder options.
 240    /// </summary>
 241    /// <param name="configure">A delegate to configure the options.</param>
 242    public WorkflowManagementFeature ConfigureWorkflowReferenceGraph(Action<WorkflowReferenceGraphOptions> configure)
 243    {
 0244        Services.Configure(configure);
 0245        return this;
 246    }
 247
 248    /// <inheritdoc />
 249    [RequiresUnreferencedCode("The assembly containing the specified marker type will be scanned for activity types.")]
 250    public override void Configure()
 251    {
 3252        AddActivitiesFrom<WorkflowManagementFeature>();
 3253    }
 254
 255    /// <inheritdoc />
 256    public override void Apply()
 257    {
 3258        Services
 3259             .AddMemoryStore<WorkflowDefinition, MemoryWorkflowDefinitionStore>()
 3260             .AddMemoryStore<WorkflowInstance, MemoryWorkflowInstanceStore>()
 3261             .AddActivityProvider<TypedActivityProvider>()
 3262             .AddActivityProvider<WorkflowDefinitionActivityProvider>()
 3263             .AddActivityProvider<HostMethodActivityProvider>()
 3264             .AddScoped<IHostMethodActivityDescriber, HostMethodActivityDescriber>()
 3265             .AddScoped<IHostMethodParameterValueProvider, DefaultHostMethodParameterValueProvider>()
 3266             .AddScoped<WorkflowDefinitionActivityDescriptorFactory>()
 3267             .AddScoped<WorkflowDefinitionActivityProvider>()
 3268             .AddScoped<IWorkflowDefinitionActivityRegistryUpdater, WorkflowDefinitionActivityRegistryUpdater>()
 3269             .AddScoped<IMaterializerRegistry, MaterializerRegistry>()
 3270             .AddScoped<IWorkflowDefinitionService, WorkflowDefinitionService>()
 3271             .AddScoped<IWorkflowSerializer, WorkflowSerializer>()
 3272             .AddScoped<IWorkflowValidator, WorkflowValidator>()
 3273             .AddScoped(_workflowReferenceQuery)
 3274             .AddScoped<IWorkflowReferenceGraphBuilder, WorkflowReferenceGraphBuilder>()
 3275             .AddScoped(_workflowDefinitionPublisher)
 3276             .AddScoped<IWorkflowDefinitionImporter, WorkflowDefinitionImporter>()
 3277             .AddScoped<IWorkflowDefinitionExporter, WorkflowDefinitionExporter>()
 3278             .AddSingleton<IFileNameSanitizer, DefaultFileNameSanitizer>()
 3279             .AddScoped<IWorkflowDefinitionManager, WorkflowDefinitionManager>()
 3280             .AddScoped<IWorkflowInstanceManager, WorkflowInstanceManager>()
 3281             .AddScoped<IWorkflowReferenceUpdater, WorkflowReferenceUpdater>()
 3282             .AddScoped<IActivityRegistryPopulator, ActivityRegistryPopulator>()
 3283             .AddSingleton<IExpressionDescriptorRegistry, ExpressionDescriptorRegistry>()
 3284             .AddSingleton<IExpressionDescriptorProvider, DefaultExpressionDescriptorProvider>()
 3285             .AddSerializationOptionsConfigurator<SerializationOptionsConfigurator>()
 3286             .AddScoped<IWorkflowMaterializer, TypedWorkflowMaterializer>()
 3287             .AddScoped<IWorkflowMaterializer, ClrWorkflowMaterializer>()
 3288             .AddScoped<IWorkflowMaterializer, JsonWorkflowMaterializer>()
 3289             .AddScoped<IActivityResolver, WorkflowDefinitionActivityResolver>()
 3290             .AddScoped<IWorkflowInstanceVariableManager, WorkflowInstanceVariableManager>()
 3291             .AddScoped<WorkflowDefinitionMapper>()
 3292             .AddSingleton<VariableDefinitionMapper>()
 3293             .AddSingleton<WorkflowStateMapper>()
 3294             ;
 295
 3296        Services
 3297            .AddNotificationHandler<DeleteWorkflowInstances>()
 3298            .AddNotificationHandler<RefreshActivityRegistry>()
 3299            .AddNotificationHandler<UpdateConsumingWorkflows>()
 3300            .AddNotificationHandler<ValidateWorkflow>()
 3301            ;
 302
 3303        Services.Configure<ManagementOptions>(options =>
 3304        {
 348305            foreach (var activityType in ActivityTypes.Distinct())
 171306                options.ActivityTypes.Add(activityType);
 3307
 267308            foreach (var descriptor in VariableDescriptors.DistinctBy(x => x.Type))
 87309                options.VariableDescriptors.Add(descriptor);
 3310
 3311            options.CompressionAlgorithm = CompressionAlgorithm;
 3312            options.LogPersistenceMode = LogPersistenceMode;
 3313            options.IsReadOnlyMode = IsReadOnlyMode;
 6314        });
 315
 6316        Services.Configure<ExpressionOptions>(options => options.RegisterTypeAlias(typeof(ClrWorkflowMaterializerContext
 6317        Services.Configure<HostMethodActivitiesOptions>(_ => { });
 6318        Services.Configure<WorkflowReferenceGraphOptions>(_ => { });
 3319    }
 320}