Merge pull request #6420 from elsa-workflows/orchard
Improve APIs for extensibility and replaceability
This commit is contained in:
commit
2c394e2353
|
|
@ -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");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,5 +12,5 @@ public interface IRequestSender
|
|||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <typeparam name="T">The type of the response.</typeparam>
|
||||
/// <returns>The response.</returns>
|
||||
Task<T?> SendAsync<T>(IRequest<T> request, CancellationToken cancellationToken = default);
|
||||
Task<T> SendAsync<T>(IRequest<T> request, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
|
@ -34,9 +34,9 @@ public class RequestContext
|
|||
/// Gets the cancellation token.
|
||||
/// </summary>
|
||||
public CancellationToken CancellationToken { get; init; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the response the request handler.
|
||||
/// </summary>
|
||||
public object? Response { get; set; }
|
||||
public object Response { get; set; } = null!;
|
||||
}
|
||||
|
|
@ -41,13 +41,13 @@ public class DefaultMediator : IMediator
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<T?> SendAsync<T>(IRequest<T> request, CancellationToken cancellationToken = default)
|
||||
public async Task<T> SendAsync<T>(IRequest<T> 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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
|||
|
|
@ -31,5 +31,5 @@ public class OrderDefinition<T, TProp>
|
|||
/// <summary>
|
||||
/// The key selector to use to order the results.
|
||||
/// </summary>
|
||||
public Expression<Func<T, TProp>> KeySelector { get; set; } = default!;
|
||||
public Expression<Func<T, TProp>> KeySelector { get; set; } = null!;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<string, object?>
|
||||
return new(new Dictionary<string, object?>
|
||||
{
|
||||
["activityInstance.status"] = context.Status.ToString()
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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<Request>
|
||||
internal class GetByDefinitionId(IWorkflowDefinitionStore store, IWorkflowDefinitionLinker linker) : ElsaEndpoint<Request>
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ namespace Elsa.Workflows;
|
|||
public abstract class Trigger : Activity, ITrigger
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected Trigger(string? source = default, int? line = default) : base(source, line)
|
||||
protected Trigger(string? source = null, int? line = null) : base(source, line)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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<TResult> : Activity<TResult>, 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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace Elsa.Workflows.UIHints.CheckList;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public abstract class CheckListOptionsProviderBase : IPropertyUIHandler
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async ValueTask<IDictionary<string, object>> 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<string, object>
|
||||
{
|
||||
[InputUIHints.CheckList] = props
|
||||
};
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement this to provide items to the dropdown list.
|
||||
/// </summary>
|
||||
protected abstract ValueTask<ICollection<CheckListItem>> GetItemsAsync(PropertyInfo propertyInfo, object? context, CancellationToken cancellationToken);
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ public class StaticCheckListOptionsProvider : IPropertyUIHandler
|
|||
|
||||
var props = new CheckListProps
|
||||
{
|
||||
CheckList = new CheckList
|
||||
CheckList = new()
|
||||
{
|
||||
Items = selectListItems.ToList()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,16 @@ public interface IWorkflowDefinitionPublisher
|
|||
/// </summary>
|
||||
/// <param name="root">Optionally provide the root activity. If not specified, <see cref="Sequence" /> will be used/></param>
|
||||
/// <returns>The new workflow definition.</returns>
|
||||
WorkflowDefinition New(IActivity? root = default);
|
||||
[Obsolete( "Use NewAsync instead.", error: false)]
|
||||
WorkflowDefinition New(IActivity? root = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new workflow definition.
|
||||
/// </summary>
|
||||
/// <param name="root">Optionally provide the root activity. If not specified, <see cref="Sequence" /> will be used/></param>
|
||||
/// <param name="cancellationToken">A cancellation token</param>
|
||||
/// <returns>The new workflow definition.</returns>
|
||||
Task<WorkflowDefinition> NewAsync(IActivity? root = null, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a workflow definition.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,6 @@ public static class WorkflowInstanceStoreExtensions
|
|||
/// </summary>
|
||||
public static async ValueTask<WorkflowInstance?> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
|||
/// <summary>
|
||||
/// Configures workflow definition storage.
|
||||
/// </summary>
|
||||
public class WorkflowDefinitionsFeature : FeatureBase
|
||||
public class WorkflowDefinitionsFeature(IModule module) : FeatureBase(module)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public WorkflowDefinitionsFeature(IModule module) : base(module)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The factory to create new instances of <see cref="IWorkflowDefinitionStore"/>.
|
||||
/// </summary>
|
||||
public Func<IServiceProvider, IWorkflowDefinitionStore> WorkflowDefinitionStore { get; set; } = sp => sp.GetRequiredService<MemoryWorkflowDefinitionStore>();
|
||||
public Func<Type> FindWorkflowDefinitionHandler { get; set; } = () => typeof(FindWorkflowDefinitionHandler);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Apply()
|
||||
{
|
||||
Services
|
||||
.AddScoped(WorkflowDefinitionStore)
|
||||
.AddScoped(typeof(IRequestHandler), FindWorkflowDefinitionHandler())
|
||||
;
|
||||
.AddScoped(WorkflowDefinitionStore);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<IServiceProvider, IWorkflowDefinitionPublisher> _workflowDefinitionPublisher = sp => ActivatorUtilities.CreateInstance<WorkflowDefinitionPublisher>(sp);
|
||||
|
||||
private string CompressionAlgorithm { get; set; } = nameof(None);
|
||||
private LogPersistenceMode LogPersistenceMode { get; set; } = LogPersistenceMode.Include;
|
||||
private bool IsReadOnlyMode { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public WorkflowManagementFeature(IModule module) : base(module)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A set of activity types to make available to the system.
|
||||
/// </summary>
|
||||
|
|
@ -194,6 +191,12 @@ public class WorkflowManagementFeature : FeatureBase
|
|||
return this;
|
||||
}
|
||||
|
||||
public WorkflowManagementFeature WithWorkflowDefinitionPublisher(Func<IServiceProvider, IWorkflowDefinitionPublisher> workflowDefinitionPublisher)
|
||||
{
|
||||
_workflowDefinitionPublisher = workflowDefinitionPublisher;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[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<IWorkflowDefinitionService, WorkflowDefinitionService>()
|
||||
.AddScoped<IWorkflowSerializer, WorkflowSerializer>()
|
||||
.AddScoped<IWorkflowValidator, WorkflowValidator>()
|
||||
.AddScoped<IWorkflowDefinitionPublisher, WorkflowDefinitionPublisher>()
|
||||
.AddScoped(_workflowDefinitionPublisher)
|
||||
.AddScoped<IWorkflowDefinitionImporter, WorkflowDefinitionImporter>()
|
||||
.AddScoped<IWorkflowDefinitionManager, WorkflowDefinitionManager>()
|
||||
.AddScoped<IWorkflowInstanceManager, WorkflowInstanceManager>()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Deletes workflow instances when a workflow definition or version is deleted.
|
||||
|
|
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// A workflow definition notifications handler for evicting the cache of the workflow definition service.
|
||||
|
|
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the <see cref="IActivityRegistry"/> for the <see cref="WorkflowDefinitionActivityProvider"/> provider whenever an <see cref="WorkflowDefinition"/> is published, retracted or deleted.
|
||||
|
|
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Updates consuming workflows when a workflow definition is published.
|
||||
|
|
@ -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<WorkflowDefinitionValidating>
|
||||
{
|
||||
|
|
@ -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<FindWorkflowDefinitionRequest, WorkflowDefinition?>
|
||||
{
|
||||
public async Task<WorkflowDefinition?> HandleAsync(FindWorkflowDefinitionRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var filter = new WorkflowDefinitionFilter
|
||||
{
|
||||
DefinitionId = request.DefinitionId,
|
||||
VersionOptions = request.VersionOptions
|
||||
};
|
||||
|
||||
var order = new WorkflowDefinitionOrder<int>(x => x.Version, OrderDirection.Descending);
|
||||
var definition = (await store.FindManyAsync(filter, order, cancellationToken: cancellationToken)).FirstOrDefault();
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
/// <summary>
|
||||
/// The workflow definition to save.
|
||||
/// </summary>
|
||||
public WorkflowDefinitionModel Model { get; set; } = default!;
|
||||
public WorkflowDefinitionModel Model { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the workflow definition should be published.
|
||||
|
|
|
|||
|
|
@ -7,52 +7,80 @@ namespace Elsa.Workflows.Management.Models;
|
|||
/// Represents a serializable workflow definition.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public record WorkflowDefinitionModel(
|
||||
string Id,
|
||||
string DefinitionId,
|
||||
string? TenantId,
|
||||
string? Name,
|
||||
string? Description,
|
||||
DateTimeOffset CreatedAt,
|
||||
int Version,
|
||||
Version? ToolVersion,
|
||||
ICollection<VariableDefinition>? Variables,
|
||||
ICollection<InputDefinition>? Inputs,
|
||||
ICollection<OutputDefinition>? Outputs,
|
||||
ICollection<string>? Outcomes,
|
||||
IDictionary<string, object>? CustomProperties,
|
||||
bool IsReadonly,
|
||||
bool IsSystem,
|
||||
bool IsLatest,
|
||||
bool IsPublished,
|
||||
WorkflowOptions? Options,
|
||||
[property: Obsolete("Use Options.UsableAsActivity instead")]
|
||||
bool? UsableAsActivity,
|
||||
IActivity? Root
|
||||
)
|
||||
public class WorkflowDefinitionModel
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public WorkflowDefinitionModel() : this(
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!,
|
||||
default!)
|
||||
/// <summary>
|
||||
/// Represents a serializable workflow definition.
|
||||
/// </summary>
|
||||
public WorkflowDefinitionModel() { }
|
||||
|
||||
/// <summary>
|
||||
/// Represents a serializable workflow definition.
|
||||
/// </summary>
|
||||
public WorkflowDefinitionModel(string id,
|
||||
string definitionId,
|
||||
string? tenantId,
|
||||
string? name,
|
||||
string? description,
|
||||
DateTimeOffset createdAt,
|
||||
int version,
|
||||
Version? toolVersion,
|
||||
ICollection<VariableDefinition>? variables,
|
||||
ICollection<InputDefinition>? inputs,
|
||||
ICollection<OutputDefinition>? outputs,
|
||||
ICollection<string>? outcomes,
|
||||
IDictionary<string, object>? 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<VariableDefinition>? Variables { get; set; }
|
||||
public ICollection<InputDefinition>? Inputs { get; set; }
|
||||
public ICollection<OutputDefinition>? Outputs { get; set; }
|
||||
public ICollection<string>? Outcomes { get; set; }
|
||||
public IDictionary<string, object>? 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; }
|
||||
}
|
||||
|
|
@ -51,12 +51,12 @@ public class WorkflowDefinitionSummary
|
|||
/// <summary>
|
||||
/// The version ID of the workflow definition.
|
||||
/// </summary>
|
||||
public string Id { get; set; } = default!;
|
||||
public string Id { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the workflow definition.
|
||||
/// </summary>
|
||||
public string DefinitionId { get; set; } = default!;
|
||||
public string DefinitionId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the workflow definition.
|
||||
|
|
@ -96,7 +96,7 @@ public class WorkflowDefinitionSummary
|
|||
/// <summary>
|
||||
/// The materializer name of the workflow definition.
|
||||
/// </summary>
|
||||
public string MaterializerName { get; set; } = default!;
|
||||
public string MaterializerName { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The timestamp when the workflow definition was created.
|
||||
|
|
|
|||
|
|
@ -33,32 +33,31 @@ public class WorkflowInstanceSummary
|
|||
/// <summary>
|
||||
/// Returns a summary view of the specified <see cref="WorkflowInstance"/>.
|
||||
/// </summary>
|
||||
public static Expression<Func<WorkflowInstance, WorkflowInstanceSummary>> 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<Func<WorkflowInstance, WorkflowInstanceSummary>> 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
|
||||
};
|
||||
|
||||
|
||||
/// <summary>The ID of the workflow instance.</summary>
|
||||
public string Id { get; set; } = default!;
|
||||
public string Id { get; set; } = null!;
|
||||
|
||||
/// <summary>The ID of the workflow definition.</summary>
|
||||
public string DefinitionId { get; set; } = default!;
|
||||
public string DefinitionId { get; set; } = null!;
|
||||
|
||||
/// <summary>The version ID of the workflow definition.</summary>
|
||||
public string DefinitionVersionId { get; set; } = default!;
|
||||
public string DefinitionVersionId { get; set; } = null!;
|
||||
|
||||
/// <summary>The version of the workflow definition.</summary>
|
||||
public int Version { get; set; }
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
using Elsa.Common.Models;
|
||||
using Elsa.Mediator.Contracts;
|
||||
using Elsa.Workflows.Management.Entities;
|
||||
|
||||
namespace Elsa.Workflows.Management.Requests;
|
||||
|
||||
/// <summary>
|
||||
/// A request to find a workflow definition.
|
||||
/// </summary>
|
||||
/// <param name="DefinitionId">The ID of the workflow definition.</param>
|
||||
/// <param name="VersionOptions">The version options.</param>
|
||||
public record FindWorkflowDefinitionRequest(string DefinitionId, VersionOptions VersionOptions) : IRequest<WorkflowDefinition?>;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<WorkflowDefinition> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<PublishWorkflowDefinitionResult> 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<WorkflowValidationError>
|
||||
{
|
||||
|
|
@ -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<WorkflowDefinition>());
|
||||
await notificationSender.SendAsync(new WorkflowDefinitionPublished(definition, affectedWorkflows), cancellationToken);
|
||||
await mediator.SendAsync(new WorkflowDefinitionPublished(definition, affectedWorkflows), cancellationToken);
|
||||
return new(true, validationErrors, affectedWorkflows);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<WorkflowDefinition?> 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 })
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<WorkflowDefinition?> FindWorkflowDefinitionAsync(string definitionId, VersionOptions versionOptions, CancellationToken cancellationToken = default)
|
||||
public Task<WorkflowDefinition?> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<WorkflowDefinition?> FindWorkflowDefinitionAsync(string definitionVersionId, CancellationToken cancellationToken = default)
|
||||
public Task<WorkflowDefinition?> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<WorkflowDefinition?> 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(
|
|||
/// <inheritdoc />
|
||||
public async Task<WorkflowGraph?> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
|||
|
|
@ -10,22 +10,22 @@ public class StoredTrigger : Entity
|
|||
/// <summary>
|
||||
/// The ID of the workflow definition.
|
||||
/// </summary>
|
||||
public string WorkflowDefinitionId { get; set; } = default!;
|
||||
public string WorkflowDefinitionId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The version ID of the workflow definition.
|
||||
/// </summary>
|
||||
public string WorkflowDefinitionVersionId { get; set; } = default!;
|
||||
public string WorkflowDefinitionVersionId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the trigger.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = default!;
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the activity associated with the trigger.
|
||||
/// </summary>
|
||||
public string ActivityId { get; set; } = default!;
|
||||
public string ActivityId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The hash of the trigger.
|
||||
|
|
|
|||
|
|
@ -11,17 +11,17 @@ public class WorkflowExecutionLogRecord : Entity, ILogRecord
|
|||
/// <summary>
|
||||
/// The ID of the workflow definition.
|
||||
/// </summary>
|
||||
public string WorkflowDefinitionId { get; set; } = default!;
|
||||
public string WorkflowDefinitionId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The version ID of the workflow definition.
|
||||
/// </summary>
|
||||
public string WorkflowDefinitionVersionId { get; set; } = default!;
|
||||
public string WorkflowDefinitionVersionId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the workflow instance.
|
||||
/// </summary>
|
||||
public string WorkflowInstanceId { get; set; } = default!;
|
||||
public string WorkflowInstanceId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The version of the workflow definition.
|
||||
|
|
@ -31,7 +31,7 @@ public class WorkflowExecutionLogRecord : Entity, ILogRecord
|
|||
/// <summary>
|
||||
/// The ID of the activity instance.
|
||||
/// </summary>
|
||||
public string ActivityInstanceId { get; set; } = default!;
|
||||
public string ActivityInstanceId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the parent activity instance.
|
||||
|
|
@ -41,12 +41,12 @@ public class WorkflowExecutionLogRecord : Entity, ILogRecord
|
|||
/// <summary>
|
||||
/// The ID of the activity.
|
||||
/// </summary>
|
||||
public string ActivityId { get; set; } = default!;
|
||||
public string ActivityId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The type of the activity.
|
||||
/// </summary>
|
||||
public string ActivityType { get; set; } = default!;
|
||||
public string ActivityType { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The version of the activity type.
|
||||
|
|
@ -61,7 +61,7 @@ public class WorkflowExecutionLogRecord : Entity, ILogRecord
|
|||
/// <summary>
|
||||
/// The unique ID of the node within the workflow graph.
|
||||
/// </summary>
|
||||
public string ActivityNodeId { get; set; } = default!;
|
||||
public string ActivityNodeId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The time stamp of the log entry.
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ public class TaskReporter(IBookmarkQueue bookmarkQueue, IStimulusHasher stimulus
|
|||
private static readonly string ActivityTypeName = ActivityTypeNameHelper.GenerateTypeName<RunTask>();
|
||||
|
||||
/// <inheritdoc />
|
||||
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<string, object>
|
||||
{
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ public static class ModuleExtensions
|
|||
/// <summary>
|
||||
/// Creates a new Elsa module and adds the <see cref="ElsaFeature"/> to it.
|
||||
/// </summary>
|
||||
public static IModule AddElsa(this IServiceCollection services, Action<IModule>? configure = default)
|
||||
public static IModule AddElsa(this IServiceCollection services, Action<IModule>? configure = null)
|
||||
{
|
||||
var module = services.GetOrCreateModule();
|
||||
module.Configure<AppFeature>(app => app.Configurator = configure);
|
||||
module.Configure<AppFeature>(app => app.Configurator += configure);
|
||||
module.Apply();
|
||||
|
||||
return module;
|
||||
|
|
@ -27,7 +27,7 @@ public static class ModuleExtensions
|
|||
/// <summary>
|
||||
/// Configures the Elsa module.
|
||||
/// </summary>
|
||||
public static IModule ConfigureElsa(this IServiceCollection services, Action<IModule>? configure = default)
|
||||
public static IModule ConfigureElsa(this IServiceCollection services, Action<IModule>? configure = null)
|
||||
{
|
||||
var module = services.GetOrCreateModule();
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,8 @@ namespace Elsa.Features;
|
|||
/// A wrapper for invoking application-specific configuration, ensuring it is invoked lastly.
|
||||
/// </summary>
|
||||
[DependsOn(typeof(ElsaFeature))]
|
||||
public class AppFeature : FeatureBase
|
||||
public class AppFeature(IModule module) : FeatureBase(module)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public AppFeature(IModule module) : base(module)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The configurator to invoke.
|
||||
/// </summary>
|
||||
|
|
|
|||
Loading…
Reference in a new issue