diff --git a/src/apps/Elsa.Server.Web/Program.cs b/src/apps/Elsa.Server.Web/Program.cs index 32fdbfc5c..d26da8a7e 100644 --- a/src/apps/Elsa.Server.Web/Program.cs +++ b/src/apps/Elsa.Server.Web/Program.cs @@ -662,7 +662,7 @@ services elsa.UseTenantHttpRouting(tenantHttpRouting => { // Override the tenant header name with a custom one. - tenantHttpRouting.WithTenantHeader("X-Company-Id"); + tenantHttpRouting.WithTenantHeader("X-Tenant-ID"); }); } diff --git a/src/common/Elsa.Mediator/Contracts/IRequestSender.cs b/src/common/Elsa.Mediator/Contracts/IRequestSender.cs index de23cd440..82c96fc74 100644 --- a/src/common/Elsa.Mediator/Contracts/IRequestSender.cs +++ b/src/common/Elsa.Mediator/Contracts/IRequestSender.cs @@ -12,5 +12,5 @@ public interface IRequestSender /// The cancellation token. /// The type of the response. /// The response. - Task SendAsync(IRequest request, CancellationToken cancellationToken = default); + Task SendAsync(IRequest request, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/common/Elsa.Mediator/Middleware/Request/RequestContext.cs b/src/common/Elsa.Mediator/Middleware/Request/RequestContext.cs index b6093cb68..b6643a567 100644 --- a/src/common/Elsa.Mediator/Middleware/Request/RequestContext.cs +++ b/src/common/Elsa.Mediator/Middleware/Request/RequestContext.cs @@ -34,9 +34,9 @@ public class RequestContext /// Gets the cancellation token. /// public CancellationToken CancellationToken { get; init; } - + /// /// Gets the response the request handler. /// - public object? Response { get; set; } + public object Response { get; set; } = null!; } \ No newline at end of file diff --git a/src/common/Elsa.Mediator/Services/DefaultMediator.cs b/src/common/Elsa.Mediator/Services/DefaultMediator.cs index 21b3c36c0..23a68162b 100644 --- a/src/common/Elsa.Mediator/Services/DefaultMediator.cs +++ b/src/common/Elsa.Mediator/Services/DefaultMediator.cs @@ -41,13 +41,13 @@ public class DefaultMediator : IMediator } /// - public async Task SendAsync(IRequest request, CancellationToken cancellationToken = default) + public async Task SendAsync(IRequest request, CancellationToken cancellationToken = default) { var responseType = typeof(T); var context = new RequestContext(request, responseType, cancellationToken); await _requestPipeline.ExecuteAsync(context); - return (T?)context.Response; + return (T)context.Response; } /// diff --git a/src/modules/Elsa.Common/Entities/OrderDefinition.cs b/src/modules/Elsa.Common/Entities/OrderDefinition.cs index 5d1f1ed82..99108ec84 100644 --- a/src/modules/Elsa.Common/Entities/OrderDefinition.cs +++ b/src/modules/Elsa.Common/Entities/OrderDefinition.cs @@ -31,5 +31,5 @@ public class OrderDefinition /// /// The key selector to use to order the results. /// - public Expression> KeySelector { get; set; } = default!; + public Expression> KeySelector { get; set; } = null!; } \ No newline at end of file diff --git a/src/modules/Elsa.Http/Features/HttpFeature.cs b/src/modules/Elsa.Http/Features/HttpFeature.cs index 65c0e42d8..085a5c4ab 100644 --- a/src/modules/Elsa.Http/Features/HttpFeature.cs +++ b/src/modules/Elsa.Http/Features/HttpFeature.cs @@ -15,7 +15,6 @@ using Elsa.Http.Services; using Elsa.Http.Tasks; using Elsa.Http.UIHints; using Elsa.Workflows; -using Elsa.Workflows.Management.Requests; using FluentStorage; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.StaticFiles; diff --git a/src/modules/Elsa.OpenTelemetry/Middleware/OpenTelemetryTracingActivityExecutionMiddleware.cs b/src/modules/Elsa.OpenTelemetry/Middleware/OpenTelemetryTracingActivityExecutionMiddleware.cs index d5c5fdc7b..0045fde75 100644 --- a/src/modules/Elsa.OpenTelemetry/Middleware/OpenTelemetryTracingActivityExecutionMiddleware.cs +++ b/src/modules/Elsa.OpenTelemetry/Middleware/OpenTelemetryTracingActivityExecutionMiddleware.cs @@ -29,16 +29,16 @@ public class OpenTelemetryTracingActivityExecutionMiddleware(ActivityMiddlewareD span.SetTag("activity.type", activity.Type); span.SetTag("activity.name", activity.Name); span.SetTag("activityInstance.id", context.Id); - span.SetTag("activityExecution.startTimeUtc", span.StartTimeUtc); + span.SetTag("activityExecution.startTimeUtc", span.StartTimeUtc); span.SetTag("tenantId", context.WorkflowExecutionContext.Workflow.Identity.TenantId); - span.AddEvent(new ActivityEvent("Executing", tags: CreateStatusTags(context))); + span.AddEvent(new("Executing", tags: CreateStatusTags(context))); await next(context); if (context.Status == ActivityStatus.Faulted) { - span.AddEvent(new ActivityEvent("Faulted", tags: CreateStatusTags(context))); + span.AddEvent(new("Faulted", tags: CreateStatusTags(context))); span.SetStatus(ActivityStatusCode.Error); span.SetTag("error", true); span.SetTag("activityInstance.hasIncidents", true); @@ -51,7 +51,7 @@ public class OpenTelemetryTracingActivityExecutionMiddleware(ActivityMiddlewareD } else { - span.AddEvent(new ActivityEvent("Executed", tags: CreateStatusTags(context))); + span.AddEvent(new("Executed", tags: CreateStatusTags(context))); span.SetStatus(ActivityStatusCode.Ok); } @@ -62,7 +62,7 @@ public class OpenTelemetryTracingActivityExecutionMiddleware(ActivityMiddlewareD private ActivityTagsCollection CreateStatusTags(ActivityExecutionContext context) { - return new ActivityTagsCollection(new Dictionary + return new(new Dictionary { ["activityInstance.status"] = context.Status.ToString() }); diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/GetByDefinitionId/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/GetByDefinitionId/Endpoint.cs index 7f87e67f1..4b2fbe9e7 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/GetByDefinitionId/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/GetByDefinitionId/Endpoint.cs @@ -1,13 +1,13 @@ using Elsa.Abstractions; using Elsa.Common.Models; -using Elsa.Mediator.Contracts; -using Elsa.Workflows.Management.Requests; +using Elsa.Workflows.Management; +using Elsa.Workflows.Models; using JetBrains.Annotations; namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.GetByDefinitionId; [PublicAPI] -internal class GetByDefinitionId(IMediator mediator, IWorkflowDefinitionLinker linker) : ElsaEndpoint +internal class GetByDefinitionId(IWorkflowDefinitionStore store, IWorkflowDefinitionLinker linker) : ElsaEndpoint { public override void Configure() { @@ -18,8 +18,8 @@ internal class GetByDefinitionId(IMediator mediator, IWorkflowDefinitionLinker l public override async Task HandleAsync(Request request, CancellationToken cancellationToken) { var versionOptions = request.VersionOptions != null ? VersionOptions.FromString(request.VersionOptions) : VersionOptions.Latest; - var findRequest = new FindWorkflowDefinitionRequest(request.DefinitionId, versionOptions); - var definition = await mediator.SendAsync(findRequest, cancellationToken); + var filter = WorkflowDefinitionHandle.ByDefinitionId(request.DefinitionId, versionOptions).ToFilter(); + var definition = await store.FindAsync(filter, cancellationToken); if (definition == null) { diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post/Endpoint.cs index 4b1ba32f4..0c8f9c509 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Post/Endpoint.cs @@ -50,7 +50,7 @@ internal class Post( // Create a new workflow in case no existing definition was found. if (isNew) { - draft = workflowDefinitionPublisher.New(); + draft = await workflowDefinitionPublisher.NewAsync(cancellationToken: cancellationToken); if (!string.IsNullOrWhiteSpace(definitionId)) draft.DefinitionId = definitionId; diff --git a/src/modules/Elsa.Workflows.Api/Models/LinkedWorkflowDefinitionModel.cs b/src/modules/Elsa.Workflows.Api/Models/LinkedWorkflowDefinitionModel.cs index ae4aa8233..d05d72d30 100644 --- a/src/modules/Elsa.Workflows.Api/Models/LinkedWorkflowDefinitionModel.cs +++ b/src/modules/Elsa.Workflows.Api/Models/LinkedWorkflowDefinitionModel.cs @@ -3,4 +3,7 @@ using Elsa.Workflows.Management.Models; namespace Elsa.Workflows.Api.Models; -public record LinkedWorkflowDefinitionModel(Link[]? Links) : WorkflowDefinitionModel; +public class LinkedWorkflowDefinitionModel(Link[]? links) : WorkflowDefinitionModel +{ + public Link[]? Links { get; init; } = links; +} diff --git a/src/modules/Elsa.Workflows.Core/Abstractions/Trigger.cs b/src/modules/Elsa.Workflows.Core/Abstractions/Trigger.cs index f26460b85..648fbe451 100644 --- a/src/modules/Elsa.Workflows.Core/Abstractions/Trigger.cs +++ b/src/modules/Elsa.Workflows.Core/Abstractions/Trigger.cs @@ -6,12 +6,12 @@ namespace Elsa.Workflows; public abstract class Trigger : Activity, ITrigger { /// - protected Trigger(string? source = default, int? line = default) : base(source, line) + protected Trigger(string? source = null, int? line = null) : base(source, line) { } /// - protected Trigger(string activityType, int version = 1, string? source = default, int? line = default) : base(activityType, version, source, line) + protected Trigger(string activityType, int version = 1, string? source = null, int? line = null) : base(activityType, version, source, line) { } @@ -39,11 +39,11 @@ public abstract class Trigger : Activity, ITrigger public abstract class Trigger : Activity, ITrigger { - protected Trigger(string? source = default, int? line = default) : base(source, line) + protected Trigger(string? source = null, int? line = null) : base(source, line) { } - protected Trigger(string activityType, int version = 1, string? source = default, int? line = default) : base(activityType, version, source, line) + protected Trigger(string activityType, int version = 1, string? source = null, int? line = null) : base(activityType, version, source, line) { } diff --git a/src/modules/Elsa.Workflows.Core/UIHints/CheckList/DropDownOptionsProviderBase.cs b/src/modules/Elsa.Workflows.Core/UIHints/CheckList/DropDownOptionsProviderBase.cs new file mode 100644 index 000000000..3d68c217d --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/UIHints/CheckList/DropDownOptionsProviderBase.cs @@ -0,0 +1,35 @@ +using System.Reflection; + +namespace Elsa.Workflows.UIHints.CheckList; + +/// +/// A base class for providing options to populate a checklist UI component. This class is intended to be inherited to implement +/// custom checklist data logic by overriding the `GetItemsAsync` method. +/// +public abstract class CheckListOptionsProviderBase : IPropertyUIHandler +{ + /// + public async ValueTask> GetUIPropertiesAsync(PropertyInfo propertyInfo, object? context, CancellationToken cancellationToken = default) + { + var items = await GetItemsAsync(propertyInfo, context, cancellationToken); + var props = new CheckListProps + { + CheckList = new() + { + Items = items.ToList() + } + }; + + var options = new Dictionary + { + [InputUIHints.CheckList] = props + }; + + return options; + } + + /// + /// Implement this to provide items to the dropdown list. + /// + protected abstract ValueTask> GetItemsAsync(PropertyInfo propertyInfo, object? context, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/UIHints/CheckList/StaticCheckListOptionsProvider.cs b/src/modules/Elsa.Workflows.Core/UIHints/CheckList/StaticCheckListOptionsProvider.cs index 38426e266..52ede3106 100644 --- a/src/modules/Elsa.Workflows.Core/UIHints/CheckList/StaticCheckListOptionsProvider.cs +++ b/src/modules/Elsa.Workflows.Core/UIHints/CheckList/StaticCheckListOptionsProvider.cs @@ -25,7 +25,7 @@ public class StaticCheckListOptionsProvider : IPropertyUIHandler var props = new CheckListProps { - CheckList = new CheckList + CheckList = new() { Items = selectListItems.ToList() } diff --git a/src/modules/Elsa.Workflows.Management/Contracts/IWorkflowDefinitionPublisher.cs b/src/modules/Elsa.Workflows.Management/Contracts/IWorkflowDefinitionPublisher.cs index 40c767e3e..c9df69142 100644 --- a/src/modules/Elsa.Workflows.Management/Contracts/IWorkflowDefinitionPublisher.cs +++ b/src/modules/Elsa.Workflows.Management/Contracts/IWorkflowDefinitionPublisher.cs @@ -17,7 +17,16 @@ public interface IWorkflowDefinitionPublisher /// /// Optionally provide the root activity. If not specified, will be used/> /// The new workflow definition. - WorkflowDefinition New(IActivity? root = default); + [Obsolete( "Use NewAsync instead.", error: false)] + WorkflowDefinition New(IActivity? root = null); + + /// + /// Creates a new workflow definition. + /// + /// Optionally provide the root activity. If not specified, will be used/> + /// A cancellation token + /// The new workflow definition. + Task NewAsync(IActivity? root = null, CancellationToken cancellationToken = default); /// /// Publishes a workflow definition. diff --git a/src/modules/Elsa.Workflows.Management/Extensions/WorkflowDefinitionHandleExtensions.cs b/src/modules/Elsa.Workflows.Management/Extensions/WorkflowDefinitionHandleExtensions.cs new file mode 100644 index 000000000..9d277b76c --- /dev/null +++ b/src/modules/Elsa.Workflows.Management/Extensions/WorkflowDefinitionHandleExtensions.cs @@ -0,0 +1,17 @@ +using Elsa.Workflows.Management.Filters; +using Elsa.Workflows.Models; + +namespace Elsa.Workflows.Management; + +public static class WorkflowDefinitionHandleExtensions +{ + public static WorkflowDefinitionFilter ToFilter(this WorkflowDefinitionHandle handle) + { + return new() + { + DefinitionId = handle.DefinitionId, + Id = handle.DefinitionVersionId, + VersionOptions = handle.VersionOptions + }; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Extensions/WorkflowInstanceStoreExtensions.cs b/src/modules/Elsa.Workflows.Management/Extensions/WorkflowInstanceStoreExtensions.cs index f41d0325d..d26e07ea4 100644 --- a/src/modules/Elsa.Workflows.Management/Extensions/WorkflowInstanceStoreExtensions.cs +++ b/src/modules/Elsa.Workflows.Management/Extensions/WorkflowInstanceStoreExtensions.cs @@ -15,6 +15,6 @@ public static class WorkflowInstanceStoreExtensions /// public static async ValueTask FindAsync(this IWorkflowInstanceStore store, string id, CancellationToken cancellationToken = default) { - return await store.FindAsync(new WorkflowInstanceFilter{ Id = id }, cancellationToken); + return await store.FindAsync(new() { Id = id }, cancellationToken); } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Features/CachingWorkflowDefinitionsFeature.cs b/src/modules/Elsa.Workflows.Management/Features/CachingWorkflowDefinitionsFeature.cs index d9d666b75..df939d6cc 100644 --- a/src/modules/Elsa.Workflows.Management/Features/CachingWorkflowDefinitionsFeature.cs +++ b/src/modules/Elsa.Workflows.Management/Features/CachingWorkflowDefinitionsFeature.cs @@ -1,7 +1,7 @@ using Elsa.Features.Abstractions; using Elsa.Features.Services; using Elsa.Workflows.Management.Handlers; -using Elsa.Workflows.Management.Handlers.Notification; +using Elsa.Workflows.Management.Handlers.Notifications; using Elsa.Workflows.Management.Services; using Elsa.Workflows.Management.Stores; using Microsoft.Extensions.DependencyInjection; diff --git a/src/modules/Elsa.Workflows.Management/Features/WorkflowDefinitionsFeature.cs b/src/modules/Elsa.Workflows.Management/Features/WorkflowDefinitionsFeature.cs index 916ad3c67..8425c991d 100644 --- a/src/modules/Elsa.Workflows.Management/Features/WorkflowDefinitionsFeature.cs +++ b/src/modules/Elsa.Workflows.Management/Features/WorkflowDefinitionsFeature.cs @@ -1,9 +1,5 @@ using Elsa.Features.Abstractions; using Elsa.Features.Services; -using Elsa.Mediator.Contracts; -using Elsa.Workflows.Management.Entities; -using Elsa.Workflows.Management.Handlers.Request; -using Elsa.Workflows.Management.Requests; using Elsa.Workflows.Management.Stores; using Microsoft.Extensions.DependencyInjection; @@ -12,25 +8,17 @@ namespace Elsa.Workflows.Management.Features; /// /// Configures workflow definition storage. /// -public class WorkflowDefinitionsFeature : FeatureBase +public class WorkflowDefinitionsFeature(IModule module) : FeatureBase(module) { - /// - public WorkflowDefinitionsFeature(IModule module) : base(module) - { - } - /// /// The factory to create new instances of . /// public Func WorkflowDefinitionStore { get; set; } = sp => sp.GetRequiredService(); - public Func FindWorkflowDefinitionHandler { get; set; } = () => typeof(FindWorkflowDefinitionHandler); /// public override void Apply() { Services - .AddScoped(WorkflowDefinitionStore) - .AddScoped(typeof(IRequestHandler), FindWorkflowDefinitionHandler()) - ; + .AddScoped(WorkflowDefinitionStore); } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs b/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs index 016bdb488..71bf63fe0 100644 --- a/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs +++ b/src/modules/Elsa.Workflows.Management/Features/WorkflowManagementFeature.cs @@ -18,7 +18,7 @@ using Elsa.Workflows.Management.Compression; using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Handlers; -using Elsa.Workflows.Management.Handlers.Notification; +using Elsa.Workflows.Management.Handlers.Notifications; using Elsa.Workflows.Management.Mappers; using Elsa.Workflows.Management.Materializers; using Elsa.Workflows.Management.Models; @@ -41,8 +41,8 @@ namespace Elsa.Workflows.Management.Features; [DependsOn(typeof(WorkflowsFeature))] [DependsOn(typeof(WorkflowDefinitionsFeature))] [DependsOn(typeof(WorkflowInstancesFeature))] -[PublicAPI] -public class WorkflowManagementFeature : FeatureBase +[UsedImplicitly] +public class WorkflowManagementFeature(IModule module) : FeatureBase(module) { private const string PrimitivesCategory = "Primitives"; private const string LookupsCategory = "Lookups"; @@ -50,15 +50,12 @@ public class WorkflowManagementFeature : FeatureBase private const string DataCategory = "Data"; private const string SystemCategory = "System"; + private Func _workflowDefinitionPublisher = sp => ActivatorUtilities.CreateInstance(sp); + private string CompressionAlgorithm { get; set; } = nameof(None); private LogPersistenceMode LogPersistenceMode { get; set; } = LogPersistenceMode.Include; private bool IsReadOnlyMode { get; set; } - /// - public WorkflowManagementFeature(IModule module) : base(module) - { - } - /// /// A set of activity types to make available to the system. /// @@ -194,6 +191,12 @@ public class WorkflowManagementFeature : FeatureBase return this; } + public WorkflowManagementFeature WithWorkflowDefinitionPublisher(Func workflowDefinitionPublisher) + { + _workflowDefinitionPublisher = workflowDefinitionPublisher; + return this; + } + /// [RequiresUnreferencedCode("The assembly containing the specified marker type will be scanned for activity types.")] public override void Configure() @@ -214,7 +217,7 @@ public class WorkflowManagementFeature : FeatureBase .AddScoped() .AddScoped() .AddScoped() - .AddScoped() + .AddScoped(_workflowDefinitionPublisher) .AddScoped() .AddScoped() .AddScoped() diff --git a/src/modules/Elsa.Workflows.Management/Filters/WorkflowInstanceFilter.cs b/src/modules/Elsa.Workflows.Management/Filters/WorkflowInstanceFilter.cs index f279df52a..15deb1e41 100644 --- a/src/modules/Elsa.Workflows.Management/Filters/WorkflowInstanceFilter.cs +++ b/src/modules/Elsa.Workflows.Management/Filters/WorkflowInstanceFilter.cs @@ -134,7 +134,7 @@ public class WorkflowInstanceFilter if (TimestampFilters != null) { - foreach (TimestampFilter timestampFilter in TimestampFilters) + foreach (var timestampFilter in TimestampFilters) { var column = timestampFilter.Column; var timestamp = timestampFilter.Timestamp; diff --git a/src/modules/Elsa.Workflows.Management/Handlers/Notification/DeleteWorkflowInstances.cs b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/DeleteWorkflowInstances.cs similarity index 97% rename from src/modules/Elsa.Workflows.Management/Handlers/Notification/DeleteWorkflowInstances.cs rename to src/modules/Elsa.Workflows.Management/Handlers/Notifications/DeleteWorkflowInstances.cs index 01429d33a..3fec484ce 100644 --- a/src/modules/Elsa.Workflows.Management/Handlers/Notification/DeleteWorkflowInstances.cs +++ b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/DeleteWorkflowInstances.cs @@ -3,7 +3,7 @@ using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Management.Notifications; using JetBrains.Annotations; -namespace Elsa.Workflows.Management.Handlers.Notification; +namespace Elsa.Workflows.Management.Handlers.Notifications; /// /// Deletes workflow instances when a workflow definition or version is deleted. diff --git a/src/modules/Elsa.Workflows.Management/Handlers/Notification/EvictWorkflowDefinitionServiceCache.cs b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/EvictWorkflowDefinitionServiceCache.cs similarity index 97% rename from src/modules/Elsa.Workflows.Management/Handlers/Notification/EvictWorkflowDefinitionServiceCache.cs rename to src/modules/Elsa.Workflows.Management/Handlers/Notifications/EvictWorkflowDefinitionServiceCache.cs index 3cc7f15da..f3802e958 100644 --- a/src/modules/Elsa.Workflows.Management/Handlers/Notification/EvictWorkflowDefinitionServiceCache.cs +++ b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/EvictWorkflowDefinitionServiceCache.cs @@ -2,7 +2,7 @@ using Elsa.Mediator.Contracts; using Elsa.Workflows.Management.Notifications; using JetBrains.Annotations; -namespace Elsa.Workflows.Management.Handlers.Notification; +namespace Elsa.Workflows.Management.Handlers.Notifications; /// /// A workflow definition notifications handler for evicting the cache of the workflow definition service. diff --git a/src/modules/Elsa.Workflows.Management/Handlers/Notification/RefreshActivityRegistry.cs b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/RefreshActivityRegistry.cs similarity index 98% rename from src/modules/Elsa.Workflows.Management/Handlers/Notification/RefreshActivityRegistry.cs rename to src/modules/Elsa.Workflows.Management/Handlers/Notifications/RefreshActivityRegistry.cs index bad83d829..87aedf89c 100644 --- a/src/modules/Elsa.Workflows.Management/Handlers/Notification/RefreshActivityRegistry.cs +++ b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/RefreshActivityRegistry.cs @@ -5,7 +5,7 @@ using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Notifications; using JetBrains.Annotations; -namespace Elsa.Workflows.Management.Handlers.Notification; +namespace Elsa.Workflows.Management.Handlers.Notifications; /// /// Refreshes the for the provider whenever an is published, retracted or deleted. diff --git a/src/modules/Elsa.Workflows.Management/Handlers/Notification/UpdateConsumingWorkflows.cs b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/UpdateConsumingWorkflows.cs similarity index 92% rename from src/modules/Elsa.Workflows.Management/Handlers/Notification/UpdateConsumingWorkflows.cs rename to src/modules/Elsa.Workflows.Management/Handlers/Notifications/UpdateConsumingWorkflows.cs index 1e3819d4b..aee801e10 100644 --- a/src/modules/Elsa.Workflows.Management/Handlers/Notification/UpdateConsumingWorkflows.cs +++ b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/UpdateConsumingWorkflows.cs @@ -2,7 +2,7 @@ using Elsa.Extensions; using Elsa.Mediator.Contracts; using Elsa.Workflows.Management.Notifications; -namespace Elsa.Workflows.Management.Handlers.Notification; +namespace Elsa.Workflows.Management.Handlers.Notifications; /// /// Updates consuming workflows when a workflow definition is published. diff --git a/src/modules/Elsa.Workflows.Management/Handlers/Notification/ValidateWorkflow.cs b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/ValidateWorkflow.cs similarity index 95% rename from src/modules/Elsa.Workflows.Management/Handlers/Notification/ValidateWorkflow.cs rename to src/modules/Elsa.Workflows.Management/Handlers/Notifications/ValidateWorkflow.cs index 4e3ed5258..e56800f81 100644 --- a/src/modules/Elsa.Workflows.Management/Handlers/Notification/ValidateWorkflow.cs +++ b/src/modules/Elsa.Workflows.Management/Handlers/Notifications/ValidateWorkflow.cs @@ -3,7 +3,7 @@ using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Notifications; using Elsa.Workflows.Models; -namespace Elsa.Workflows.Management.Handlers.Notification; +namespace Elsa.Workflows.Management.Handlers.Notifications; public class ValidateWorkflow : INotificationHandler { diff --git a/src/modules/Elsa.Workflows.Management/Handlers/Request/FindWorkflowDefinitionHandler.cs b/src/modules/Elsa.Workflows.Management/Handlers/Request/FindWorkflowDefinitionHandler.cs deleted file mode 100644 index 0febd0442..000000000 --- a/src/modules/Elsa.Workflows.Management/Handlers/Request/FindWorkflowDefinitionHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Elsa.Common.Entities; -using Elsa.Mediator.Contracts; -using Elsa.Workflows.Management.Entities; -using Elsa.Workflows.Management.Filters; -using Elsa.Workflows.Management.Requests; - -namespace Elsa.Workflows.Management.Handlers.Request; - -public class FindWorkflowDefinitionHandler(IWorkflowDefinitionStore store) : IRequestHandler -{ - public async Task HandleAsync(FindWorkflowDefinitionRequest request, CancellationToken cancellationToken) - { - var filter = new WorkflowDefinitionFilter - { - DefinitionId = request.DefinitionId, - VersionOptions = request.VersionOptions - }; - - var order = new WorkflowDefinitionOrder(x => x.Version, OrderDirection.Descending); - var definition = (await store.FindManyAsync(filter, order, cancellationToken: cancellationToken)).FirstOrDefault(); - return definition; - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Models/SaveWorkflowDefinitionRequest.cs b/src/modules/Elsa.Workflows.Management/Models/SaveWorkflowDefinitionRequest.cs index fad1f539a..14715b618 100644 --- a/src/modules/Elsa.Workflows.Management/Models/SaveWorkflowDefinitionRequest.cs +++ b/src/modules/Elsa.Workflows.Management/Models/SaveWorkflowDefinitionRequest.cs @@ -8,7 +8,7 @@ /// /// The workflow definition to save. /// - public WorkflowDefinitionModel Model { get; set; } = default!; + public WorkflowDefinitionModel Model { get; set; } = null!; /// /// Whether the workflow definition should be published. diff --git a/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionModel.cs b/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionModel.cs index 6b1859334..598155655 100644 --- a/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionModel.cs +++ b/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionModel.cs @@ -7,52 +7,80 @@ namespace Elsa.Workflows.Management.Models; /// Represents a serializable workflow definition. /// [PublicAPI] -public record WorkflowDefinitionModel( - string Id, - string DefinitionId, - string? TenantId, - string? Name, - string? Description, - DateTimeOffset CreatedAt, - int Version, - Version? ToolVersion, - ICollection? Variables, - ICollection? Inputs, - ICollection? Outputs, - ICollection? Outcomes, - IDictionary? CustomProperties, - bool IsReadonly, - bool IsSystem, - bool IsLatest, - bool IsPublished, - WorkflowOptions? Options, - [property: Obsolete("Use Options.UsableAsActivity instead")] - bool? UsableAsActivity, - IActivity? Root -) +public class WorkflowDefinitionModel { - /// - public WorkflowDefinitionModel() : this( - default!, - default!, - default!, - default!, - default!, - default!, - default!, - default!, - default!, - default!, - default!, - default, - default!, - default!, - default!, - default!, - default!, - default!, - default!, - default!) + /// + /// Represents a serializable workflow definition. + /// + public WorkflowDefinitionModel() { } + + /// + /// Represents a serializable workflow definition. + /// + public WorkflowDefinitionModel(string id, + string definitionId, + string? tenantId, + string? name, + string? description, + DateTimeOffset createdAt, + int version, + Version? toolVersion, + ICollection? variables, + ICollection? inputs, + ICollection? outputs, + ICollection? outcomes, + IDictionary? customProperties, + bool isReadonly, + bool isSystem, + bool isLatest, + bool isPublished, + WorkflowOptions? options, + bool? usableAsActivity, + IActivity? root) { + Id = id; + DefinitionId = definitionId; + TenantId = tenantId; + Name = name; + Description = description; + CreatedAt = createdAt; + Version = version; + ToolVersion = toolVersion; + Variables = variables; + Inputs = inputs; + Outputs = outputs; + Outcomes = outcomes; + CustomProperties = customProperties; + IsReadonly = isReadonly; + IsSystem = isSystem; + IsLatest = isLatest; + IsPublished = isPublished; + Options = options; + UsableAsActivity = usableAsActivity; + Root = root; } + + public string Id { get; set; } + public string DefinitionId { get; set; } + public string? TenantId { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } + public DateTimeOffset CreatedAt { get; set; } + public int Version { get; set; } + public Version? ToolVersion { get; set; } + public ICollection? Variables { get; set; } + public ICollection? Inputs { get; set; } + public ICollection? Outputs { get; set; } + public ICollection? Outcomes { get; set; } + public IDictionary? CustomProperties { get; set; } + public bool IsReadonly { get; set; } + public bool IsSystem { get; set; } + public bool IsLatest { get; set; } + public bool IsPublished { get; set; } + public WorkflowOptions? Options { get; set; } + + [Obsolete("Use Options.UsableAsActivity instead")] + public bool? UsableAsActivity { get; set; } + + public IActivity? Root { get; set; } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionSummary.cs b/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionSummary.cs index 718cdd7e7..2f8a71a45 100644 --- a/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionSummary.cs +++ b/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionSummary.cs @@ -51,12 +51,12 @@ public class WorkflowDefinitionSummary /// /// The version ID of the workflow definition. /// - public string Id { get; set; } = default!; + public string Id { get; set; } = null!; /// /// The ID of the workflow definition. /// - public string DefinitionId { get; set; } = default!; + public string DefinitionId { get; set; } = null!; /// /// The name of the workflow definition. @@ -96,7 +96,7 @@ public class WorkflowDefinitionSummary /// /// The materializer name of the workflow definition. /// - public string MaterializerName { get; set; } = default!; + public string MaterializerName { get; set; } = null!; /// /// The timestamp when the workflow definition was created. diff --git a/src/modules/Elsa.Workflows.Management/Models/WorkflowInstanceSummary.cs b/src/modules/Elsa.Workflows.Management/Models/WorkflowInstanceSummary.cs index 97346b24b..ef673127a 100644 --- a/src/modules/Elsa.Workflows.Management/Models/WorkflowInstanceSummary.cs +++ b/src/modules/Elsa.Workflows.Management/Models/WorkflowInstanceSummary.cs @@ -33,32 +33,31 @@ public class WorkflowInstanceSummary /// /// Returns a summary view of the specified . /// - public static Expression> FromInstanceExpression() - => workflowInstance => new WorkflowInstanceSummary - { - Id = workflowInstance.Id, - DefinitionId = workflowInstance.DefinitionId, - DefinitionVersionId = workflowInstance.DefinitionVersionId, - Version = workflowInstance.Version, - Status = workflowInstance.Status, - SubStatus = workflowInstance.SubStatus, - CorrelationId = workflowInstance.CorrelationId, - Name = workflowInstance.Name, - IncidentCount = workflowInstance.IncidentCount, - CreatedAt = workflowInstance.CreatedAt, - UpdatedAt = workflowInstance.UpdatedAt, - FinishedAt = workflowInstance.FinishedAt - }; + public static Expression> FromInstanceExpression() => workflowInstance => new() + { + Id = workflowInstance.Id, + DefinitionId = workflowInstance.DefinitionId, + DefinitionVersionId = workflowInstance.DefinitionVersionId, + Version = workflowInstance.Version, + Status = workflowInstance.Status, + SubStatus = workflowInstance.SubStatus, + CorrelationId = workflowInstance.CorrelationId, + Name = workflowInstance.Name, + IncidentCount = workflowInstance.IncidentCount, + CreatedAt = workflowInstance.CreatedAt, + UpdatedAt = workflowInstance.UpdatedAt, + FinishedAt = workflowInstance.FinishedAt + }; /// The ID of the workflow instance. - public string Id { get; set; } = default!; + public string Id { get; set; } = null!; /// The ID of the workflow definition. - public string DefinitionId { get; set; } = default!; + public string DefinitionId { get; set; } = null!; /// The version ID of the workflow definition. - public string DefinitionVersionId { get; set; } = default!; + public string DefinitionVersionId { get; set; } = null!; /// The version of the workflow definition. public int Version { get; set; } diff --git a/src/modules/Elsa.Workflows.Management/Requests/FindWorkflowDefinitionRequest.cs b/src/modules/Elsa.Workflows.Management/Requests/FindWorkflowDefinitionRequest.cs deleted file mode 100644 index a539d5aa5..000000000 --- a/src/modules/Elsa.Workflows.Management/Requests/FindWorkflowDefinitionRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Elsa.Common.Models; -using Elsa.Mediator.Contracts; -using Elsa.Workflows.Management.Entities; - -namespace Elsa.Workflows.Management.Requests; - -/// -/// A request to find a workflow definition. -/// -/// The ID of the workflow definition. -/// The version options. -public record FindWorkflowDefinitionRequest(string DefinitionId, VersionOptions VersionOptions) : IRequest; \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionImporter.cs b/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionImporter.cs index b63260be4..4081b3b2b 100644 --- a/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionImporter.cs +++ b/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionImporter.cs @@ -43,7 +43,7 @@ namespace Elsa.Workflows.Management.Services // Create a new workflow in case no existing definition was found. if (isNew) { - draft = _workflowDefinitionPublisher.New(); + draft = await _workflowDefinitionPublisher.NewAsync(cancellationToken: cancellationToken); if (!string.IsNullOrWhiteSpace(definitionId)) draft.DefinitionId = definitionId; diff --git a/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionPublisher.cs b/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionPublisher.cs index ab60f6558..88640c69d 100644 --- a/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionPublisher.cs +++ b/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionPublisher.cs @@ -3,13 +3,12 @@ using Elsa.Common.Entities; using Elsa.Common.Models; using Elsa.Mediator.Contracts; using Elsa.Workflows.Activities; -using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Management.Materializers; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Notifications; -using Elsa.Workflows.Management.Requests; +using Elsa.Workflows.Models; namespace Elsa.Workflows.Management.Services; @@ -18,9 +17,9 @@ public class WorkflowDefinitionPublisher( IWorkflowDefinitionService workflowDefinitionService, IWorkflowDefinitionStore workflowDefinitionStore, IWorkflowValidator workflowValidator, - INotificationSender notificationSender, IIdentityGenerator identityGenerator, IActivitySerializer activitySerializer, + IMediator mediator, ISystemClock systemClock) : IWorkflowDefinitionPublisher { @@ -45,16 +44,34 @@ public class WorkflowDefinitionPublisher( }; } + public Task NewAsync(IActivity? root = null, CancellationToken cancellationToken = default) + { + root ??= new Sequence(); + var id = identityGenerator.GenerateId(); + var definitionId = identityGenerator.GenerateId(); + const int version = 1; + + var workflowDefinition = new WorkflowDefinition + { + Id = id, + DefinitionId = definitionId, + Version = version, + IsLatest = true, + IsPublished = false, + CreatedAt = systemClock.UtcNow, + StringData = activitySerializer.Serialize(root), + MaterializerName = JsonWorkflowMaterializer.MaterializerName + }; + + return Task.FromResult(workflowDefinition); + } + /// public async Task PublishAsync(string definitionId, CancellationToken cancellationToken = default) { - var filter = new WorkflowDefinitionFilter - { - DefinitionId = definitionId, - VersionOptions = VersionOptions.Latest - }; + var filter = WorkflowDefinitionHandle.ByDefinitionId(definitionId, VersionOptions.Latest).ToFilter(); var definition = await workflowDefinitionStore.FindAsync(filter, cancellationToken); - + if (definition == null) return new(false, new List { @@ -73,16 +90,15 @@ public class WorkflowDefinitionPublisher( if (validationErrors.Any()) return new(false, validationErrors, new([])); - await notificationSender.SendAsync(new WorkflowDefinitionPublishing(definition), cancellationToken); + await mediator.SendAsync(new WorkflowDefinitionPublishing(definition), cancellationToken); var definitionId = definition.DefinitionId; // Reset current latest and published definitions. - var filter = new WorkflowDefinitionFilter + var publishedWorkflows = await workflowDefinitionStore.FindManyAsync(new() { DefinitionId = definitionId, VersionOptions = VersionOptions.LatestOrPublished - }; - var publishedWorkflows = await workflowDefinitionStore.FindManyAsync(filter, cancellationToken); + }, cancellationToken); foreach (var publishedAndOrLatestWorkflow in publishedWorkflows) { @@ -92,27 +108,23 @@ public class WorkflowDefinitionPublisher( await workflowDefinitionStore.SaveAsync(publishedAndOrLatestWorkflow, cancellationToken); if (isPublished) - await notificationSender.SendAsync(new WorkflowDefinitionVersionRetracted(publishedAndOrLatestWorkflow), cancellationToken); + await mediator.SendAsync(new WorkflowDefinitionVersionRetracted(publishedAndOrLatestWorkflow), cancellationToken); } - // Save the new published definition. + // Save the newly published definition. definition.IsPublished = true; definition = Initialize(definition); await workflowDefinitionStore.SaveAsync(definition, cancellationToken); var affectedWorkflows = new AffectedWorkflows(new List()); - await notificationSender.SendAsync(new WorkflowDefinitionPublished(definition, affectedWorkflows), cancellationToken); + await mediator.SendAsync(new WorkflowDefinitionPublished(definition, affectedWorkflows), cancellationToken); return new(true, validationErrors, affectedWorkflows); } /// public async Task RetractAsync(string definitionId, CancellationToken cancellationToken = default) { - var filter = new WorkflowDefinitionFilter - { - DefinitionId = definitionId, - VersionOptions = VersionOptions.Published - }; + var filter = WorkflowDefinitionHandle.ByDefinitionId(definitionId, VersionOptions.Published).ToFilter(); var definition = await workflowDefinitionStore.FindAsync(filter, cancellationToken); if (definition == null) @@ -129,9 +141,9 @@ public class WorkflowDefinitionPublisher( definition.IsPublished = false; - await notificationSender.SendAsync(new WorkflowDefinitionRetracting(definition), cancellationToken); + await mediator.SendAsync(new WorkflowDefinitionRetracting(definition), cancellationToken); await workflowDefinitionStore.SaveAsync(definition, cancellationToken); - await notificationSender.SendAsync(new WorkflowDefinitionRetracted(definition), cancellationToken); + await mediator.SendAsync(new WorkflowDefinitionRetracted(definition), cancellationToken); return definition; } @@ -184,10 +196,8 @@ public class WorkflowDefinitionPublisher( await workflowDefinitionStore.SaveAsync(draft, cancellationToken); - if (lastVersion is null) - { - await notificationSender.SendAsync(new WorkflowDefinitionCreated(definition), cancellationToken); - } + if (lastVersion is null) + await mediator.SendAsync(new WorkflowDefinitionCreated(definition), cancellationToken); if (lastVersion is { IsPublished: true, IsLatest: true }) { diff --git a/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionService.cs b/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionService.cs index 3ecc175c4..bd3435846 100644 --- a/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionService.cs +++ b/src/modules/Elsa.Workflows.Management/Services/WorkflowDefinitionService.cs @@ -19,40 +19,30 @@ public class WorkflowDefinitionService( var materializer = workflowMaterializers.FirstOrDefault(x => x.Name == definition.MaterializerName); if (materializer == null) - throw new Exception("Provider not found"); + throw new("Provider not found"); var workflow = await materializer.MaterializeAsync(definition, cancellationToken); return await workflowGraphBuilder.BuildAsync(workflow, cancellationToken); } /// - public async Task FindWorkflowDefinitionAsync(string definitionId, VersionOptions versionOptions, CancellationToken cancellationToken = default) + public Task FindWorkflowDefinitionAsync(string definitionId, VersionOptions versionOptions, CancellationToken cancellationToken = default) { - var filter = new WorkflowDefinitionFilter - { - DefinitionId = definitionId, - VersionOptions = versionOptions - }; - return await workflowDefinitionStore.FindAsync(filter, cancellationToken); + var handle = WorkflowDefinitionHandle.ByDefinitionId(definitionId, versionOptions); + return FindWorkflowDefinitionAsync(handle, cancellationToken); } /// - public async Task FindWorkflowDefinitionAsync(string definitionVersionId, CancellationToken cancellationToken = default) + public Task FindWorkflowDefinitionAsync(string definitionVersionId, CancellationToken cancellationToken = default) { - var filter = new WorkflowDefinitionFilter - { - Id = definitionVersionId - }; - return await workflowDefinitionStore.FindAsync(filter, cancellationToken); + var handle = WorkflowDefinitionHandle.ByDefinitionVersionId(definitionVersionId); + return FindWorkflowDefinitionAsync(handle, cancellationToken); } /// public async Task FindWorkflowDefinitionAsync(WorkflowDefinitionHandle handle, CancellationToken cancellationToken = default) { - var filter = new WorkflowDefinitionFilter - { - DefinitionHandle = handle - }; + var filter = handle.ToFilter(); return await workflowDefinitionStore.FindAsync(filter, cancellationToken); } @@ -87,12 +77,12 @@ public class WorkflowDefinitionService( /// public async Task FindWorkflowGraphAsync(WorkflowDefinitionHandle definitionHandle, CancellationToken cancellationToken = default) { - var filter = new WorkflowDefinitionFilter - { - DefinitionHandle = definitionHandle - }; + var definition = await FindWorkflowDefinitionAsync(definitionHandle, cancellationToken); - return await FindWorkflowGraphAsync(filter, cancellationToken); + if (definition == null) + return null; + + return await MaterializeWorkflowAsync(definition, cancellationToken); } /// diff --git a/src/modules/Elsa.Workflows.Runtime/Entities/StoredTrigger.cs b/src/modules/Elsa.Workflows.Runtime/Entities/StoredTrigger.cs index 75fe494d6..d404fbfb9 100644 --- a/src/modules/Elsa.Workflows.Runtime/Entities/StoredTrigger.cs +++ b/src/modules/Elsa.Workflows.Runtime/Entities/StoredTrigger.cs @@ -10,22 +10,22 @@ public class StoredTrigger : Entity /// /// The ID of the workflow definition. /// - public string WorkflowDefinitionId { get; set; } = default!; + public string WorkflowDefinitionId { get; set; } = null!; /// /// The version ID of the workflow definition. /// - public string WorkflowDefinitionVersionId { get; set; } = default!; + public string WorkflowDefinitionVersionId { get; set; } = null!; /// /// The name of the trigger. /// - public string Name { get; set; } = default!; + public string Name { get; set; } = null!; /// /// The ID of the activity associated with the trigger. /// - public string ActivityId { get; set; } = default!; + public string ActivityId { get; set; } = null!; /// /// The hash of the trigger. diff --git a/src/modules/Elsa.Workflows.Runtime/Entities/WorkflowExecutionLogRecord.cs b/src/modules/Elsa.Workflows.Runtime/Entities/WorkflowExecutionLogRecord.cs index 87460d6b6..54c412db1 100644 --- a/src/modules/Elsa.Workflows.Runtime/Entities/WorkflowExecutionLogRecord.cs +++ b/src/modules/Elsa.Workflows.Runtime/Entities/WorkflowExecutionLogRecord.cs @@ -11,17 +11,17 @@ public class WorkflowExecutionLogRecord : Entity, ILogRecord /// /// The ID of the workflow definition. /// - public string WorkflowDefinitionId { get; set; } = default!; + public string WorkflowDefinitionId { get; set; } = null!; /// /// The version ID of the workflow definition. /// - public string WorkflowDefinitionVersionId { get; set; } = default!; + public string WorkflowDefinitionVersionId { get; set; } = null!; /// /// The ID of the workflow instance. /// - public string WorkflowInstanceId { get; set; } = default!; + public string WorkflowInstanceId { get; set; } = null!; /// /// The version of the workflow definition. @@ -31,7 +31,7 @@ public class WorkflowExecutionLogRecord : Entity, ILogRecord /// /// The ID of the activity instance. /// - public string ActivityInstanceId { get; set; } = default!; + public string ActivityInstanceId { get; set; } = null!; /// /// The ID of the parent activity instance. @@ -41,12 +41,12 @@ public class WorkflowExecutionLogRecord : Entity, ILogRecord /// /// The ID of the activity. /// - public string ActivityId { get; set; } = default!; + public string ActivityId { get; set; } = null!; /// /// The type of the activity. /// - public string ActivityType { get; set; } = default!; + public string ActivityType { get; set; } = null!; /// /// The version of the activity type. @@ -61,7 +61,7 @@ public class WorkflowExecutionLogRecord : Entity, ILogRecord /// /// The unique ID of the node within the workflow graph. /// - public string ActivityNodeId { get; set; } = default!; + public string ActivityNodeId { get; set; } = null!; /// /// The time stamp of the log entry. diff --git a/src/modules/Elsa.Workflows.Runtime/Services/TaskReporter.cs b/src/modules/Elsa.Workflows.Runtime/Services/TaskReporter.cs index 560276b7e..54f86614f 100644 --- a/src/modules/Elsa.Workflows.Runtime/Services/TaskReporter.cs +++ b/src/modules/Elsa.Workflows.Runtime/Services/TaskReporter.cs @@ -11,9 +11,9 @@ public class TaskReporter(IBookmarkQueue bookmarkQueue, IStimulusHasher stimulus private static readonly string ActivityTypeName = ActivityTypeNameHelper.GenerateTypeName(); /// - public async Task ReportCompletionAsync(string taskId, object? result = default, CancellationToken cancellationToken = default) + public async Task ReportCompletionAsync(string taskId, object? result = null, CancellationToken cancellationToken = default) { - var stimulus = new RunTaskStimulus(taskId, default!); + var stimulus = new RunTaskStimulus(taskId, null!); var input = new Dictionary { @@ -24,7 +24,7 @@ public class TaskReporter(IBookmarkQueue bookmarkQueue, IStimulusHasher stimulus { ActivityTypeName = ActivityTypeName, StimulusHash = stimulusHasher.Hash(ActivityTypeName, stimulus), - Options = new ResumeBookmarkOptions + Options = new() { Input = input } diff --git a/src/modules/Elsa/Extensions/DependencyInjectionExtensions.cs b/src/modules/Elsa/Extensions/DependencyInjectionExtensions.cs index 51805f5a2..53b363962 100644 --- a/src/modules/Elsa/Extensions/DependencyInjectionExtensions.cs +++ b/src/modules/Elsa/Extensions/DependencyInjectionExtensions.cs @@ -15,10 +15,10 @@ public static class ModuleExtensions /// /// Creates a new Elsa module and adds the to it. /// - public static IModule AddElsa(this IServiceCollection services, Action? configure = default) + public static IModule AddElsa(this IServiceCollection services, Action? configure = null) { var module = services.GetOrCreateModule(); - module.Configure(app => app.Configurator = configure); + module.Configure(app => app.Configurator += configure); module.Apply(); return module; @@ -27,7 +27,7 @@ public static class ModuleExtensions /// /// Configures the Elsa module. /// - public static IModule ConfigureElsa(this IServiceCollection services, Action? configure = default) + public static IModule ConfigureElsa(this IServiceCollection services, Action? configure = null) { var module = services.GetOrCreateModule(); diff --git a/src/modules/Elsa/Features/AppFeature.cs b/src/modules/Elsa/Features/AppFeature.cs index 0a72a3396..775b19981 100644 --- a/src/modules/Elsa/Features/AppFeature.cs +++ b/src/modules/Elsa/Features/AppFeature.cs @@ -8,13 +8,8 @@ namespace Elsa.Features; /// A wrapper for invoking application-specific configuration, ensuring it is invoked lastly. /// [DependsOn(typeof(ElsaFeature))] -public class AppFeature : FeatureBase +public class AppFeature(IModule module) : FeatureBase(module) { - /// - public AppFeature(IModule module) : base(module) - { - } - /// /// The configurator to invoke. ///