diff --git a/src/modules/Elsa.Dsl/Contracts/IFunctionActivityRegistry.cs b/src/modules/Elsa.Dsl/Contracts/IFunctionActivityRegistry.cs
index a2af20905..0b9f2001b 100644
--- a/src/modules/Elsa.Dsl/Contracts/IFunctionActivityRegistry.cs
+++ b/src/modules/Elsa.Dsl/Contracts/IFunctionActivityRegistry.cs
@@ -22,12 +22,12 @@ public interface IFunctionActivityRegistry
///
/// The descriptor that describes the function.
void RegisterFunction(FunctionActivityDescriptor descriptor);
-
+
///
/// Resolves a function to an activity that can be invoked from a DSL script.
///
/// The name of the function.
/// The arguments that are passed to the function.
/// An activity that can be invoked from a DSL script.
- IActivity ResolveFunction(string functionName, IEnumerable? arguments = default);
+ Task ResolveFunction(string functionName, IEnumerable? arguments = default);
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/VisitFunction.cs b/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/VisitFunction.cs
index 8d195e34b..b68beb4c9 100644
--- a/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/VisitFunction.cs
+++ b/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/VisitFunction.cs
@@ -27,7 +27,7 @@ public partial class WorkflowDefinitionBuilderInterpreter
var functionName = context.ID().GetText();
var argsNode = context.args();
var args = argsNode != null ? _argValues.Get(context.args()) : default;
- var activity = _functionActivityRegistry.ResolveFunction(functionName, args);
+ var activity = _functionActivityRegistry.ResolveFunction(functionName, args).GetAwaiter().GetResult();
_expressionValue.Put(context, activity);
return DefaultResult;
diff --git a/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/VisitObject.cs b/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/VisitObject.cs
index 19edf7c5f..50cc73d60 100644
--- a/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/VisitObject.cs
+++ b/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/VisitObject.cs
@@ -29,7 +29,7 @@ public partial class WorkflowDefinitionBuilderInterpreter
///
public override IWorkflowBuilder VisitObject(ElsaParser.ObjectContext context)
{
- var @object = GetObject(context);
+ var @object = GetObject(context).GetAwaiter().GetResult();
_object.Put(context, @object);
_expressionValue.Put(context, @object);
@@ -38,12 +38,12 @@ public partial class WorkflowDefinitionBuilderInterpreter
return DefaultResult;
}
- private object GetObject(ElsaParser.ObjectContext context)
+ private async Task GetObject(ElsaParser.ObjectContext context)
{
var objectTypeName = context.ID().GetText();
// First, check if the symbol matches an activity type.
- var activityDescriptor = _activityRegistry.Find(x => x.Name == objectTypeName);
+ var activityDescriptor = await _activityRegistryLookup.Find(x => x.Name == objectTypeName);
if (activityDescriptor != null)
{
diff --git a/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/WorkflowDefinitionBuilderInterpreter.cs b/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/WorkflowDefinitionBuilderInterpreter.cs
index 1474c14f9..ce0276566 100644
--- a/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/WorkflowDefinitionBuilderInterpreter.cs
+++ b/src/modules/Elsa.Dsl/Interpreters/WorkflowDefinitionBuilderInterpreter/WorkflowDefinitionBuilderInterpreter.cs
@@ -9,7 +9,7 @@ namespace Elsa.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter : ElsaParserBaseVisitor
{
private readonly ITypeSystem _typeSystem;
- private readonly IActivityRegistry _activityRegistry;
+ private readonly IActivityRegistryLookupService _activityRegistryLookup;
private readonly IFunctionActivityRegistry _functionActivityRegistry;
private readonly IWorkflowBuilder _workflowBuilder;
private readonly ParseTreeProperty _object = new();
@@ -22,12 +22,12 @@ public partial class WorkflowDefinitionBuilderInterpreter : ElsaParserBaseVisito
///
public WorkflowDefinitionBuilderInterpreter(
ITypeSystem typeSystem,
- IActivityRegistry activityRegistry,
+ IActivityRegistryLookupService activityRegistryLookup,
IFunctionActivityRegistry functionActivityRegistry,
IWorkflowBuilderFactory workflowBuilderFactory)
{
_typeSystem = typeSystem;
- _activityRegistry = activityRegistry;
+ _activityRegistryLookup = activityRegistryLookup;
_functionActivityRegistry = functionActivityRegistry;
_workflowBuilder = workflowBuilderFactory.CreateBuilder();
}
diff --git a/src/modules/Elsa.Dsl/Services/DslEngine.cs b/src/modules/Elsa.Dsl/Services/DslEngine.cs
index 91e0e2220..bcef7a99d 100644
--- a/src/modules/Elsa.Dsl/Services/DslEngine.cs
+++ b/src/modules/Elsa.Dsl/Services/DslEngine.cs
@@ -10,7 +10,7 @@ namespace Elsa.Dsl.Services;
public class DslEngine : IDslEngine
{
private readonly ITypeSystem _typeSystem;
- private readonly IActivityRegistry _activityRegistry;
+ private readonly IActivityRegistryLookupService _activityRegistryLookup;
private readonly IFunctionActivityRegistry _functionActivityRegistry;
private readonly IWorkflowBuilderFactory _workflowBuilderFactory;
@@ -19,12 +19,12 @@ public class DslEngine : IDslEngine
///
public DslEngine(
ITypeSystem typeSystem,
- IActivityRegistry activityRegistry,
+ IActivityRegistryLookupService activityRegistryLookup,
IFunctionActivityRegistry functionActivityRegistry,
IWorkflowBuilderFactory workflowBuilderFactory)
{
_typeSystem = typeSystem;
- _activityRegistry = activityRegistry;
+ _activityRegistryLookup = activityRegistryLookup;
_functionActivityRegistry = functionActivityRegistry;
_workflowBuilderFactory = workflowBuilderFactory;
}
@@ -40,7 +40,7 @@ public class DslEngine : IDslEngine
var interpreter = new WorkflowDefinitionBuilderInterpreter(
_typeSystem,
- _activityRegistry,
+ _activityRegistryLookup,
_functionActivityRegistry,
_workflowBuilderFactory);
diff --git a/src/modules/Elsa.Dsl/Services/FunctionActivityRegistry.cs b/src/modules/Elsa.Dsl/Services/FunctionActivityRegistry.cs
index 696e6dc72..eebd83277 100644
--- a/src/modules/Elsa.Dsl/Services/FunctionActivityRegistry.cs
+++ b/src/modules/Elsa.Dsl/Services/FunctionActivityRegistry.cs
@@ -12,15 +12,15 @@ namespace Elsa.Dsl.Services;
///
public class FunctionActivityRegistry : IFunctionActivityRegistry
{
- private readonly IActivityRegistry _activityRegistry;
+ private readonly IActivityRegistryLookupService _activityRegistryLookup;
private readonly IDictionary _dictionary = new Dictionary();
///
/// Creates a new instance of the class.
///
- public FunctionActivityRegistry(IActivityRegistry activityRegistry)
+ public FunctionActivityRegistry(IActivityRegistryLookupService activityRegistryLookup)
{
- _activityRegistry = activityRegistry;
+ _activityRegistryLookup = activityRegistryLookup;
}
///
@@ -37,12 +37,12 @@ public class FunctionActivityRegistry : IFunctionActivityRegistry
}
///
- public IActivity ResolveFunction(string functionName, IEnumerable? arguments = default)
+ public async Task ResolveFunction(string functionName, IEnumerable? arguments = default)
{
if (!_dictionary.TryGetValue(functionName, out var descriptor))
throw new Exception($"Could not resolve function {functionName}. Did you forget to register it?");
- var activityDescriptor = _activityRegistry.Find(x => x.Name == descriptor.ActivityTypeName || x.TypeName == descriptor.ActivityTypeName);
+ var activityDescriptor = await _activityRegistryLookup.Find(x => x.Name == descriptor.ActivityTypeName || x.TypeName == descriptor.ActivityTypeName);
if (activityDescriptor == null)
throw new Exception($"Could not find activity descriptor for activity type {descriptor.ActivityTypeName}");
diff --git a/src/modules/Elsa.JavaScript/Services/JintJavaScriptEvaluator.cs b/src/modules/Elsa.JavaScript/Services/JintJavaScriptEvaluator.cs
index 90013a0b2..36a6f3a16 100644
--- a/src/modules/Elsa.JavaScript/Services/JintJavaScriptEvaluator.cs
+++ b/src/modules/Elsa.JavaScript/Services/JintJavaScriptEvaluator.cs
@@ -100,7 +100,7 @@ public class JintJavaScriptEvaluator : IJavaScriptEvaluator
CreateWorkflowInputAccessors(engine, context);
// Create output getters for each activity.
- CreateActivityOutputAccessors(engine, context);
+ await CreateActivityOutputAccessors(engine, context);
// Create argument getters for each argument.
foreach (var argument in options.Arguments)
@@ -171,11 +171,11 @@ public class JintJavaScriptEvaluator : IJavaScriptEvaluator
}
}
- private static void CreateActivityOutputAccessors(Engine engine, ExpressionExecutionContext context)
+ private static async Task CreateActivityOutputAccessors(Engine engine, ExpressionExecutionContext context)
{
var activityOutputs = context.GetActivityOutputs();
- foreach (var activityOutput in activityOutputs)
+ await foreach (var activityOutput in activityOutputs)
foreach (var outputName in activityOutput.OutputNames)
engine.SetValue($"get{outputName}From{activityOutput.ActivityName}", (Func)(() => context.GetOutput(activityOutput.ActivityId, outputName)));
}
diff --git a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/ActivityOutputFunctionsDefinitionProvider.cs b/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/ActivityOutputFunctionsDefinitionProvider.cs
index 0588f5dab..fb52ac4c9 100644
--- a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/ActivityOutputFunctionsDefinitionProvider.cs
+++ b/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/ActivityOutputFunctionsDefinitionProvider.cs
@@ -12,13 +12,13 @@ namespace Elsa.JavaScript.TypeDefinitions.Providers;
internal class ActivityOutputFunctionsDefinitionProvider : FunctionDefinitionProvider
{
private readonly IActivityVisitor _activityVisitor;
- private readonly IActivityRegistry _activityRegistry;
+ private readonly IActivityRegistryLookupService _activityRegistryLookup;
private readonly IIdentityGraphService _identityGraphService;
- public ActivityOutputFunctionsDefinitionProvider(IActivityVisitor activityVisitor, IActivityRegistry activityRegistry, IIdentityGraphService identityGraphService)
+ public ActivityOutputFunctionsDefinitionProvider(IActivityVisitor activityVisitor, IActivityRegistryLookupService activityRegistryLookup, IIdentityGraphService identityGraphService)
{
_activityVisitor = activityVisitor;
- _activityRegistry = activityRegistry;
+ _activityRegistryLookup = activityRegistryLookup;
_identityGraphService = identityGraphService;
}
@@ -29,12 +29,12 @@ internal class ActivityOutputFunctionsDefinitionProvider : FunctionDefinitionPro
var nodes = (await _activityVisitor.VisitAsync(workflow.Root, context.CancellationToken)).Flatten().Distinct().ToList();
// Ensure identities.
- _identityGraphService.AssignIdentities(nodes);
+ await _identityGraphService.AssignIdentities(nodes);
- var activitiesWithOutputs = nodes.GetActivitiesWithOutputs(_activityRegistry);
+ var activitiesWithOutputs = nodes.GetActivitiesWithOutputs(_activityRegistryLookup);
var definitions = new List();
- foreach (var (activity, activityDescriptor) in activitiesWithOutputs)
+ await foreach (var (activity, activityDescriptor) in activitiesWithOutputs)
{
definitions.AddRange(from output in activityDescriptor.Outputs
select output.Name.Pascalize()
diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptorOptions/Get/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptorOptions/Get/Endpoint.cs
index 100ac9593..c0601f12e 100644
--- a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptorOptions/Get/Endpoint.cs
+++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptorOptions/Get/Endpoint.cs
@@ -8,14 +8,14 @@ namespace Elsa.Workflows.Api.Endpoints.ActivityDescriptorOptions.Get;
internal class Get : ElsaEndpoint
{
private readonly IServiceProvider _serviceProvider;
- private readonly IActivityRegistry _registry;
+ private readonly IActivityRegistryLookupService _registryLookup;
private readonly IPropertyUIHandlerResolver _optionsResolver;
///
- public Get(IServiceProvider serviceProvider, IActivityRegistry registry, IPropertyUIHandlerResolver optionsResolver)
+ public Get(IServiceProvider serviceProvider, IActivityRegistryLookupService registryLookup, IPropertyUIHandlerResolver optionsResolver)
{
_serviceProvider = serviceProvider;
- _registry = registry;
+ _registryLookup = registryLookup;
_optionsResolver = optionsResolver;
}
@@ -29,7 +29,7 @@ internal class Get : ElsaEndpoint
///
public override async Task HandleAsync(Request request, CancellationToken cancellationToken)
{
- var descriptor = request.Version == null ? _registry.Find(request.ActivityTypeName) : _registry.Find(request.ActivityTypeName, request.Version.Value);
+ var descriptor = request.Version == null ? await _registryLookup.Find(request.ActivityTypeName) : await _registryLookup.Find(request.ActivityTypeName, request.Version.Value);
if (descriptor == null)
await SendNotFoundAsync(cancellationToken);
diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/Get/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/Get/Endpoint.cs
index 6ef776657..459cf1635 100644
--- a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/Get/Endpoint.cs
+++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/Get/Endpoint.cs
@@ -8,12 +8,12 @@ namespace Elsa.Workflows.Api.Endpoints.ActivityDescriptors.Get;
[PublicAPI]
internal class Get : ElsaEndpoint
{
- private readonly IActivityRegistry _registry;
+ private readonly IActivityRegistryLookupService _registryLookup;
///
- public Get(IActivityRegistry registry)
+ public Get(IActivityRegistryLookupService registryLookup)
{
- _registry = registry;
+ _registryLookup = registryLookup;
}
///
@@ -26,7 +26,7 @@ internal class Get : ElsaEndpoint
///
public override async Task HandleAsync(Request request, CancellationToken cancellationToken)
{
- var descriptor = request.Version == null ? _registry.Find(request.TypeName) : _registry.Find(request.TypeName, request.Version.Value);
+ var descriptor = request.Version == null ? await _registryLookup.Find(request.TypeName) : await _registryLookup.Find(request.TypeName, request.Version.Value);
if (descriptor == null)
await SendNotFoundAsync(cancellationToken);
diff --git a/src/modules/Elsa.Workflows.Core/Builders/WorkflowBuilder.cs b/src/modules/Elsa.Workflows.Core/Builders/WorkflowBuilder.cs
index 65e1145e6..34f69d11c 100644
--- a/src/modules/Elsa.Workflows.Core/Builders/WorkflowBuilder.cs
+++ b/src/modules/Elsa.Workflows.Core/Builders/WorkflowBuilder.cs
@@ -240,7 +240,7 @@ public class WorkflowBuilder : IWorkflowBuilder
await _activityRegistry.RegisterAsync(distinctActivityTypes, cancellationToken);
// Assign identities to all activities.
- _identityGraphService.AssignIdentities(nodes);
+ await _identityGraphService.AssignIdentities(nodes);
// Give unnamed variables in each variable container a predictable name.
var variableContainers = nodes.Where(x => x.Activity is IVariableContainer).Select(x => (IVariableContainer)x.Activity).ToList();
diff --git a/src/modules/Elsa.Workflows.Core/Contexts/WorkflowExecutionContext.cs b/src/modules/Elsa.Workflows.Core/Contexts/WorkflowExecutionContext.cs
index 1af3d2301..c8d77efbd 100644
--- a/src/modules/Elsa.Workflows.Core/Contexts/WorkflowExecutionContext.cs
+++ b/src/modules/Elsa.Workflows.Core/Contexts/WorkflowExecutionContext.cs
@@ -60,6 +60,7 @@ public partial class WorkflowExecutionContext : IExecutionContext
ServiceProvider = serviceProvider;
SystemClock = serviceProvider.GetRequiredService();
ActivityRegistry = serviceProvider.GetRequiredService();
+ ActivityRegistryLookup = serviceProvider.GetRequiredService();
_hasher = serviceProvider.GetRequiredService();
SubStatus = WorkflowSubStatus.Pending;
Id = id;
@@ -152,7 +153,7 @@ public partial class WorkflowExecutionContext : IExecutionContext
cancellationTokens);
var workflowStateExtractor = serviceProvider.GetRequiredService();
- workflowStateExtractor.Apply(workflowExecutionContext, workflowState);
+ await workflowStateExtractor.Apply(workflowExecutionContext, workflowState);
return workflowExecutionContext;
}
@@ -228,6 +229,11 @@ public partial class WorkflowExecutionContext : IExecutionContext
///
public IActivityRegistry ActivityRegistry { get; }
+ ///
+ /// Gets the .
+ ///
+ public IActivityRegistryLookupService ActivityRegistryLookup { get; }
+
///
/// Gets the workflow graph.
///
@@ -572,9 +578,9 @@ public partial class WorkflowExecutionContext : IExecutionContext
///
/// Creates a new for the specified activity.
///
- public ActivityExecutionContext CreateActivityExecutionContext(IActivity activity, ActivityInvocationOptions? options = default)
+ public async Task CreateActivityExecutionContext(IActivity activity, ActivityInvocationOptions? options = default)
{
- var activityDescriptor = ActivityRegistry.Find(activity) ?? throw new Exception($"Activity with type {activity.Type} not found in registry");
+ var activityDescriptor = await ActivityRegistryLookup.Find(activity) ?? throw new Exception($"Activity with type {activity.Type} not found in registry");
var tag = options?.Tag;
var parentContext = options?.Owner;
var parentExpressionExecutionContext = parentContext?.ExpressionExecutionContext ?? ExpressionExecutionContext;
diff --git a/src/modules/Elsa.Workflows.Core/Contracts/IActivityRegistry.cs b/src/modules/Elsa.Workflows.Core/Contracts/IActivityRegistry.cs
index 0e91e44ec..c3ed1630f 100644
--- a/src/modules/Elsa.Workflows.Core/Contracts/IActivityRegistry.cs
+++ b/src/modules/Elsa.Workflows.Core/Contracts/IActivityRegistry.cs
@@ -14,13 +14,6 @@ public interface IActivityRegistry : IActivityProvider
/// The activity descriptor to add.
void Add(Type providerType, ActivityDescriptor descriptor);
- ///
- /// Adds multiple activity descriptors to the registry.
- ///
- /// The type of the activity provider.
- /// The activity descriptors to add.
- void AddMany(Type providerType, IEnumerable descriptors);
-
///
/// Removes an activity descriptor from the registry.
///
@@ -28,17 +21,6 @@ public interface IActivityRegistry : IActivityProvider
/// The activity descriptor to remove.
void Remove(Type providerType, ActivityDescriptor descriptor);
- ///
- /// Clears all activity descriptors from the registry.
- ///
- void Clear();
-
- ///
- /// Clears all activity descriptors provided by the specified provider.
- ///
- /// The type of the activity provider.
- void ClearProvider(Type providerType);
-
///
/// Returns all activity descriptors in the registry.
///
@@ -100,4 +82,12 @@ public interface IActivityRegistry : IActivityProvider
/// The activity types to register.
/// An optional cancellation token.
Task RegisterAsync(IEnumerable activityTypes, CancellationToken cancellationToken = default);
+
+ ///
+ /// Refreshes the activity descriptors in the registry by querying the specified activity providers.
+ ///
+ /// The activity providers used to retrieve the descriptors.
+ /// The cancellation token.
+ /// A task representing the asynchronous operation.
+ Task RefreshDescriptors(IEnumerable activityProviders, CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Contracts/IActivityRegistryLookupService.cs b/src/modules/Elsa.Workflows.Core/Contracts/IActivityRegistryLookupService.cs
new file mode 100644
index 000000000..93f02136a
--- /dev/null
+++ b/src/modules/Elsa.Workflows.Core/Contracts/IActivityRegistryLookupService.cs
@@ -0,0 +1,38 @@
+using Elsa.Workflows.Models;
+
+namespace Elsa.Workflows.Contracts;
+
+///
+/// Represents a service for looking up activity descriptors.
+///
+public interface IActivityRegistryLookupService
+{
+ ///
+ /// Returns the activity descriptor for the specified activity type.
+ ///
+ /// The activity type.
+ /// The activity descriptor for the specified activity type.
+ Task Find(string type);
+
+ ///
+ /// Returns the activity descriptor for the specified activity type and version.
+ ///
+ /// The activity type.
+ /// The activity version.
+ /// The activity descriptor for the specified activity type and version.
+ Task Find(string type, int version);
+
+ ///
+ /// Returns the activity descriptor matching the specified predicate.
+ ///
+ /// The predicate to match.
+ /// The activity descriptor matching the specified predicate.
+ Task Find(Func predicate);
+
+ ///
+ /// Returns all activity descriptors matching the specified predicate.
+ ///
+ /// The predicate to match.
+ /// All activity descriptors matching the specified predicate.
+ IEnumerable FindMany(Func predicate);
+}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Contracts/IIdentityGraphService.cs b/src/modules/Elsa.Workflows.Core/Contracts/IIdentityGraphService.cs
index f462ed834..4e758dc99 100644
--- a/src/modules/Elsa.Workflows.Core/Contracts/IIdentityGraphService.cs
+++ b/src/modules/Elsa.Workflows.Core/Contracts/IIdentityGraphService.cs
@@ -21,17 +21,17 @@ public interface IIdentityGraphService
///
/// Assign unique identities tot the specified graph.
///
- void AssignIdentities(ActivityNode root);
+ Task AssignIdentities(ActivityNode root);
///
/// Assign unique identities tot the specified flattened list of s.
///
- void AssignIdentities(ICollection flattenedList);
+ Task AssignIdentities(ICollection flattenedList);
///
/// Assign unique identities to input and output properties of the specified graph.
///
- void AssignInputOutputs(IActivity activity);
+ Task AssignInputOutputs(IActivity activity);
///
/// Assign unique identities to variables of the specified .
diff --git a/src/modules/Elsa.Workflows.Core/Contracts/IWorkflowStateExtractor.cs b/src/modules/Elsa.Workflows.Core/Contracts/IWorkflowStateExtractor.cs
index 6dd6b4f47..0ef1a8dc1 100644
--- a/src/modules/Elsa.Workflows.Core/Contracts/IWorkflowStateExtractor.cs
+++ b/src/modules/Elsa.Workflows.Core/Contracts/IWorkflowStateExtractor.cs
@@ -13,12 +13,12 @@ public interface IWorkflowStateExtractor
/// The workflow execution context to map.
/// The mapped workflow state.
WorkflowState Extract(WorkflowExecutionContext workflowExecutionContext);
-
+
///
/// Applies workflow state to a workflow execution context.
///
/// The workflow execution context to map onto.
/// The workflow state to apply.
/// The updated workflow execution context.
- WorkflowExecutionContext Apply(WorkflowExecutionContext workflowExecutionContext, WorkflowState state);
+ Task Apply(WorkflowExecutionContext workflowExecutionContext, WorkflowState state);
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Extensions/ActivityExecutionContextExtensions.cs b/src/modules/Elsa.Workflows.Core/Extensions/ActivityExecutionContextExtensions.cs
index d69308d04..4e88b69ac 100644
--- a/src/modules/Elsa.Workflows.Core/Extensions/ActivityExecutionContextExtensions.cs
+++ b/src/modules/Elsa.Workflows.Core/Extensions/ActivityExecutionContextExtensions.cs
@@ -138,24 +138,24 @@ public static class ActivityExecutionContextExtensions
///
/// Evaluates a specific input property of the activity.
///
- public static Task EvaluateInputPropertyAsync(this ActivityExecutionContext context, string inputName)
+ public static async Task EvaluateInputPropertyAsync(this ActivityExecutionContext context, string inputName)
{
var activity = context.Activity;
- var activityRegistry = context.GetRequiredService();
- var activityDescriptor = activityRegistry.Find(activity.Type) ?? throw new Exception("Activity descriptor not found");
+ var activityRegistryLookup = context.GetRequiredService();
+ var activityDescriptor = await activityRegistryLookup.Find(activity.Type) ?? throw new Exception("Activity descriptor not found");
var inputDescriptor = activityDescriptor.GetWrappedInputPropertyDescriptor(activity, inputName);
if (inputDescriptor == null)
throw new Exception($"No input with name {inputName} could be found");
- return EvaluateInputPropertyAsync(context, activityDescriptor, inputDescriptor);
+ return await EvaluateInputPropertyAsync(context, activityDescriptor, inputDescriptor);
}
///
/// Returns a set of tuples containing the activity and its descriptor for all activities with outputs.
///
/// The being extended.
- public static IEnumerable<(IActivity Activity, ActivityDescriptor ActivityDescriptor)> GetActivitiesWithOutputs(this ActivityExecutionContext activityExecutionContext)
+ public static async IAsyncEnumerable<(IActivity Activity, ActivityDescriptor ActivityDescriptor)> GetActivitiesWithOutputs(this ActivityExecutionContext activityExecutionContext)
{
// Get current container.
var currentContainerNode = activityExecutionContext.FindParentWithVariableContainer()?.ActivityNode;
@@ -168,28 +168,25 @@ public static class ActivityExecutionContextExtensions
var containedNodes = workflowExecutionContext.Nodes.Where(x => x.Parents.Contains(currentContainerNode)).Distinct().ToList();
// Select activities with outputs.
- var activityRegistry = workflowExecutionContext.GetRequiredService();
+ var activityRegistry = workflowExecutionContext.GetRequiredService();
var activitiesWithOutputs = containedNodes.GetActivitiesWithOutputs(activityRegistry);
- foreach (var (activity, activityDescriptor) in activitiesWithOutputs)
+ await foreach (var (activity, activityDescriptor) in activitiesWithOutputs)
yield return (activity, activityDescriptor);
}
///
/// Returns a set of tuples containing the activity and its descriptor for all activities with outputs.
///
- public static IEnumerable<(IActivity Activity, ActivityDescriptor ActivityDescriptor)> GetActivitiesWithOutputs(this IEnumerable nodes, IActivityRegistry activityRegistry)
+ public static async IAsyncEnumerable<(IActivity activity, ActivityDescriptor activityDescriptor)> GetActivitiesWithOutputs(this IEnumerable nodes, IActivityRegistryLookupService activityRegistryLookup)
{
- // Select activities with outputs.
- var activitiesWithOutputs =
- from node in nodes
- let activity = node.Activity
- let activityDescriptor = activityRegistry.Find(activity.Type, activity.Version)
- where activityDescriptor.Outputs.Any()
- select (activity, activityDescriptor);
-
- foreach (var (activity, activityDescriptor) in activitiesWithOutputs)
- yield return (activity, activityDescriptor);
+ foreach (var node in nodes)
+ {
+ var activity = node.Activity;
+ var activityDescriptor = await activityRegistryLookup.Find(activity.Type, activity.Version);
+ if (activityDescriptor != null && activityDescriptor.Outputs.Any())
+ yield return (activity, activityDescriptor);
+ }
}
///
diff --git a/src/modules/Elsa.Workflows.Core/Extensions/ActivityRegistryExtensions.cs b/src/modules/Elsa.Workflows.Core/Extensions/ActivityRegistryExtensions.cs
index 6f55f20ab..75a99b2ff 100644
--- a/src/modules/Elsa.Workflows.Core/Extensions/ActivityRegistryExtensions.cs
+++ b/src/modules/Elsa.Workflows.Core/Extensions/ActivityRegistryExtensions.cs
@@ -13,7 +13,7 @@ public static class ActivityRegistryExtensions
///
/// Finds the activity descriptor for the specified activity.
///
- public static ActivityDescriptor? Find(this IActivityRegistry activityRegistry, IActivity activity) => activityRegistry.Find(activity.Type, activity.Version);
+ public static Task Find(this IActivityRegistryLookupService activityRegistry, IActivity activity) => activityRegistry.Find(activity.Type, activity.Version);
///
/// Finds the activity descriptor for the specified activity type.
diff --git a/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs b/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs
index 8edbdb55c..4ec3e1f0c 100644
--- a/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs
+++ b/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs
@@ -434,7 +434,7 @@ public static class ExpressionExecutionContextExtensions
///
/// Returns all activity outputs.
///
- public static IEnumerable GetActivityOutputs(this ExpressionExecutionContext context)
+ public static async IAsyncEnumerable GetActivityOutputs(this ExpressionExecutionContext context)
{
if (!context.TryGetActivityExecutionContext(out var activityExecutionContext))
yield break;
@@ -445,7 +445,7 @@ public static class ExpressionExecutionContextExtensions
if (useActivityName)
activitiesWithOutputs = activitiesWithOutputs.Where(x => !string.IsNullOrWhiteSpace(x.Activity.Name));
- foreach (var activityWithOutput in activitiesWithOutputs)
+ await foreach (var activityWithOutput in activitiesWithOutputs)
{
var activity = activityWithOutput.Activity;
var activityDescriptor = activityWithOutput.ActivityDescriptor;
diff --git a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs
index 1135c85e2..2b8f36931 100644
--- a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs
+++ b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs
@@ -136,6 +136,7 @@ public class WorkflowsFeature : FeatureBase
.AddScoped(sp => ActivatorUtilities.CreateInstance(sp))
.AddSingleton()
.AddSingleton()
+ .AddScoped()
.AddSingleton()
.AddSingleton()
.AddSingleton()
diff --git a/src/modules/Elsa.Workflows.Core/Services/ActivityInvoker.cs b/src/modules/Elsa.Workflows.Core/Services/ActivityInvoker.cs
index 343f43f5e..fc33def90 100644
--- a/src/modules/Elsa.Workflows.Core/Services/ActivityInvoker.cs
+++ b/src/modules/Elsa.Workflows.Core/Services/ActivityInvoker.cs
@@ -30,7 +30,7 @@ public class ActivityInvoker : IActivityInvoker
if (activityExecutionContext == null)
{
// Create a new activity execution context.
- activityExecutionContext = workflowExecutionContext.CreateActivityExecutionContext(activity, options);
+ activityExecutionContext = await workflowExecutionContext.CreateActivityExecutionContext(activity, options);
// Add the activity context to the workflow context.
workflowExecutionContext.AddActivityExecutionContext(activityExecutionContext);
diff --git a/src/modules/Elsa.Workflows.Core/Services/ActivityRegistry.cs b/src/modules/Elsa.Workflows.Core/Services/ActivityRegistry.cs
index ccfa3ec69..b6fb1a6e8 100644
--- a/src/modules/Elsa.Workflows.Core/Services/ActivityRegistry.cs
+++ b/src/modules/Elsa.Workflows.Core/Services/ActivityRegistry.cs
@@ -7,37 +7,15 @@ using Microsoft.Extensions.Logging;
namespace Elsa.Workflows.Services;
///
-public class ActivityRegistry : IActivityRegistry
+public class ActivityRegistry(IActivityDescriber activityDescriber, IEnumerable modifiers, ILogger logger) : IActivityRegistry
{
- private readonly IActivityDescriber _activityDescriber;
- private readonly IEnumerable _modifiers;
- private readonly ILogger _logger;
private readonly ISet _manualActivityDescriptors = new HashSet();
- private readonly ConcurrentDictionary> _providedActivityDescriptors = new();
- private readonly ConcurrentDictionary<(string Type, int Version), ActivityDescriptor> _activityDescriptors = new();
-
- ///
- /// Initializes a new instance of the class.
- ///
- public ActivityRegistry(IActivityDescriber activityDescriber, IEnumerable modifiers, ILogger logger)
- {
- _activityDescriber = activityDescriber;
- _modifiers = modifiers;
- _logger = logger;
- }
+ private ConcurrentDictionary> _providedActivityDescriptors = new();
+ private ConcurrentDictionary<(string Type, int Version), ActivityDescriptor> _activityDescriptors = new();
///
public void Add(Type providerType, ActivityDescriptor descriptor) => Add(descriptor, GetOrCreateDescriptors(providerType));
- ///
- public void AddMany(Type providerType, IEnumerable descriptors)
- {
- var target = GetOrCreateDescriptors(providerType);
-
- foreach (var descriptor in descriptors)
- Add(descriptor, target);
- }
-
///
public void Remove(Type providerType, ActivityDescriptor descriptor)
{
@@ -45,24 +23,6 @@ public class ActivityRegistry : IActivityRegistry
_activityDescriptors.Remove((descriptor.TypeName, descriptor.Version), out _);
}
- ///
- public void Clear()
- {
- _activityDescriptors.Clear();
- _providedActivityDescriptors.Clear();
- }
-
- ///
- public void ClearProvider(Type providerType)
- {
- var descriptors = ListByProvider(providerType).ToList();
-
- foreach (var descriptor in descriptors)
- _activityDescriptors.Remove((descriptor.TypeName, descriptor.Version), out _);
-
- _providedActivityDescriptors.Remove(providerType, out _);
- }
-
///
public IEnumerable ListAll() => _activityDescriptors.Values;
@@ -95,7 +55,7 @@ public class ActivityRegistry : IActivityRegistry
if (_activityDescriptors.Values.Any(x => x.TypeName == activityTypeName))
return;
- var activityDescriptor = await _activityDescriber.DescribeActivityAsync(activityType, cancellationToken);
+ var activityDescriptor = await activityDescriber.DescribeActivityAsync(activityType, cancellationToken);
Add(GetType(), activityDescriptor);
_manualActivityDescriptors.Add(activityDescriptor);
}
@@ -106,24 +66,51 @@ public class ActivityRegistry : IActivityRegistry
foreach (var activityType in activityTypes)
await RegisterAsync(activityType, cancellationToken);
}
+
+ ///
+ public ValueTask> GetDescriptorsAsync(CancellationToken cancellationToken = default) => new(_manualActivityDescriptors);
+ public async Task RefreshDescriptors(IEnumerable activityProviders, CancellationToken cancellationToken = default)
+ {
+ var providersDictionary = new ConcurrentDictionary>();
+ var activityDescriptors = new ConcurrentDictionary<(string Type, int Version), ActivityDescriptor>();
+ foreach (IActivityProvider activityProvider in activityProviders)
+ {
+ var descriptors = (await activityProvider.GetDescriptorsAsync(cancellationToken)).ToList();
+ var providerDescriptors = new List();
+ providersDictionary[activityProvider.GetType()] = providerDescriptors;
+ foreach (var descriptor in descriptors)
+ {
+ Add(descriptor, activityDescriptors, providerDescriptors);
+ }
+ }
+
+ Interlocked.Exchange(ref _activityDescriptors, activityDescriptors);
+ Interlocked.Exchange(ref _providedActivityDescriptors, providersDictionary);
+ }
+
private void Add(ActivityDescriptor descriptor, ICollection target)
{
- foreach (var modifier in _modifiers)
+ Add(descriptor, _activityDescriptors, target);
+ }
+
+ private void Add(ActivityDescriptor descriptor, ConcurrentDictionary<(string Type, int Version), ActivityDescriptor> activityDescriptors, ICollection providerDescriptors)
+ {
+ foreach (var modifier in modifiers)
modifier.Modify(descriptor);
// If the descriptor already exists, replace it. But log a warning.
- if (_activityDescriptors.TryGetValue((descriptor.TypeName, descriptor.Version), out var existingDescriptor))
+ if (activityDescriptors.TryGetValue((descriptor.TypeName, descriptor.Version), out var existingDescriptor))
{
- // Remove the existing descriptor from the target collection.
- target.Remove(existingDescriptor);
+ // Remove the existing descriptor from the providerDescriptors collection.
+ providerDescriptors.Remove(existingDescriptor);
// Log a warning.
- _logger.LogWarning("Activity descriptor {ActivityType} v{ActivityVersion} was already registered. Replacing with new descriptor", descriptor.TypeName, descriptor.Version);
+ logger.LogWarning("Activity descriptor {ActivityType} v{ActivityVersion} was already registered. Replacing with new descriptor", descriptor.TypeName, descriptor.Version);
}
- _activityDescriptors[(descriptor.TypeName, descriptor.Version)] = descriptor;
- target.Add(descriptor);
+ activityDescriptors[(descriptor.TypeName, descriptor.Version)] = descriptor;
+ providerDescriptors.Add(descriptor);
}
private ICollection GetOrCreateDescriptors(Type provider)
@@ -136,7 +123,4 @@ public class ActivityRegistry : IActivityRegistry
return descriptors;
}
-
- ///
- public ValueTask> GetDescriptorsAsync(CancellationToken cancellationToken = default) => new(_manualActivityDescriptors);
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Services/ActivityRegistryLookupService.cs b/src/modules/Elsa.Workflows.Core/Services/ActivityRegistryLookupService.cs
new file mode 100644
index 000000000..3b5883ff6
--- /dev/null
+++ b/src/modules/Elsa.Workflows.Core/Services/ActivityRegistryLookupService.cs
@@ -0,0 +1,44 @@
+using Elsa.Workflows.Contracts;
+using Elsa.Workflows.Models;
+
+namespace Elsa.Workflows.Services;
+
+///
+/// Represents a service used to lookup activity descriptors in the activity registry.
+///
+public class ActivityRegistryLookupService(IActivityRegistry activityRegistry, IEnumerable providers) : IActivityRegistryLookupService
+{
+ ///
+ public Task Find(string type)
+ {
+ return Find(() => activityRegistry.Find(type));
+ }
+
+ ///
+ public Task Find(string type, int version)
+ {
+ return Find(() => activityRegistry.Find(type, version));
+ }
+
+ ///
+ public Task Find(Func predicate)
+ {
+ return Find(() => activityRegistry.Find(predicate));
+ }
+
+ ///
+ public IEnumerable FindMany(Func predicate)
+ {
+ return activityRegistry.FindMany(predicate);
+ }
+
+ private async Task Find(Func findPredicate)
+ {
+ var descriptor = findPredicate.Invoke();
+ if (descriptor is not null)
+ return descriptor;
+
+ await activityRegistry.RefreshDescriptors(providers);
+ return findPredicate.Invoke();
+ }
+}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Services/IdentityGraphService.cs b/src/modules/Elsa.Workflows.Core/Services/IdentityGraphService.cs
index 8deaa2ea0..7343aa8ab 100644
--- a/src/modules/Elsa.Workflows.Core/Services/IdentityGraphService.cs
+++ b/src/modules/Elsa.Workflows.Core/Services/IdentityGraphService.cs
@@ -10,15 +10,15 @@ namespace Elsa.Workflows.Services;
public class IdentityGraphService : IIdentityGraphService
{
private readonly IActivityVisitor _activityVisitor;
- private readonly IActivityRegistry _activityRegistry;
+ private readonly IActivityRegistryLookupService _activityRegistryLookup;
///
/// Constructor.
///
- public IdentityGraphService(IActivityVisitor activityVisitor, IActivityRegistry activityRegistry)
+ public IdentityGraphService(IActivityVisitor activityVisitor, IActivityRegistryLookupService activityRegistryLookup)
{
_activityVisitor = activityVisitor;
- _activityRegistry = activityRegistry;
+ _activityRegistryLookup = activityRegistryLookup;
}
///
@@ -31,14 +31,14 @@ public class IdentityGraphService : IIdentityGraphService
public async Task AssignIdentitiesAsync(IActivity root, CancellationToken cancellationToken = default)
{
var graph = await _activityVisitor.VisitAsync(root, cancellationToken);
- AssignIdentities(graph);
+ await AssignIdentities(graph);
}
///
- public void AssignIdentities(ActivityNode root) => AssignIdentities(root.Flatten().ToList());
+ public Task AssignIdentities(ActivityNode root) => AssignIdentities(root.Flatten().ToList());
///
- public void AssignIdentities(ICollection flattenedList)
+ public async Task AssignIdentities(ICollection flattenedList)
{
var identityCounters = new Dictionary();
@@ -46,7 +46,7 @@ public class IdentityGraphService : IIdentityGraphService
{
node.Activity.Id = CreateId(node, identityCounters, flattenedList);
node.Activity.NodeId = node.NodeId;
- AssignInputOutputs(node.Activity);
+ await AssignInputOutputs(node.Activity);
if (node.Activity is IVariableContainer variableContainer)
AssignVariables(variableContainer);
@@ -54,9 +54,9 @@ public class IdentityGraphService : IIdentityGraphService
}
///
- public void AssignInputOutputs(IActivity activity)
+ public async Task AssignInputOutputs(IActivity activity)
{
- var activityDescriptor = _activityRegistry.Find(activity.Type, activity.Version) ?? throw new Exception("Activity descriptor not found");
+ var activityDescriptor = await _activityRegistryLookup.Find(activity.Type, activity.Version) ?? throw new Exception("Activity descriptor not found");
var inputDictionary = activityDescriptor.GetWrappedInputProperties(activity);
foreach (var (inputName, input) in inputDictionary)
diff --git a/src/modules/Elsa.Workflows.Core/Services/WorkflowGraphBuilder.cs b/src/modules/Elsa.Workflows.Core/Services/WorkflowGraphBuilder.cs
index e08aa480b..62c366213 100644
--- a/src/modules/Elsa.Workflows.Core/Services/WorkflowGraphBuilder.cs
+++ b/src/modules/Elsa.Workflows.Core/Services/WorkflowGraphBuilder.cs
@@ -14,7 +14,7 @@ public class WorkflowGraphBuilder(IActivityVisitor activityVisitor, IIdentityGra
var graph = await activityVisitor.VisitAsync(workflow, cancellationToken);
var nodes = graph.Flatten().ToList();
- identityGraphService.AssignIdentities(nodes);
+ await identityGraphService.AssignIdentities(nodes);
return new WorkflowGraph(workflow, graph, nodes);
}
}
\ No newline at end of file
diff --git a/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs b/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs
index eaffc63ab..2e0cee34b 100644
--- a/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs
+++ b/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs
@@ -41,7 +41,7 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor
}
///
- public WorkflowExecutionContext Apply(WorkflowExecutionContext workflowExecutionContext, WorkflowState state)
+ public async Task Apply(WorkflowExecutionContext workflowExecutionContext, WorkflowState state)
{
workflowExecutionContext.Id = state.Id;
workflowExecutionContext.CorrelationId = state.CorrelationId;
@@ -55,7 +55,7 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor
workflowExecutionContext.FinishedAt = state.FinishedAt;
ApplyInput(state, workflowExecutionContext);
ApplyProperties(state, workflowExecutionContext);
- ApplyActivityExecutionContexts(state, workflowExecutionContext);
+ await ApplyActivityExecutionContexts(state, workflowExecutionContext);
ApplyCompletionCallbacks(state, workflowExecutionContext);
ApplyScheduledActivities(state, workflowExecutionContext);
return workflowExecutionContext;
@@ -96,10 +96,10 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor
workflowExecutionContext.Properties[property.Key] = property.Value;
}
- private static void ApplyActivityExecutionContexts(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
+ private static async Task ApplyActivityExecutionContexts(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
{
- var activityExecutionContexts = state.ActivityExecutionContexts
- .Select(CreateActivityExecutionContext)
+ var activityExecutionContexts = (await Task.WhenAll(
+ state.ActivityExecutionContexts.Select(async item => await CreateActivityExecutionContext(item))))
.Where(x => x != null)
.Select(x => x!)
.ToList();
@@ -128,7 +128,7 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor
workflowExecutionContext.ActivityExecutionContexts = activityExecutionContexts;
return;
- ActivityExecutionContext? CreateActivityExecutionContext(ActivityExecutionContextState activityExecutionContextState)
+ async Task CreateActivityExecutionContext(ActivityExecutionContextState activityExecutionContextState)
{
var activity = workflowExecutionContext.FindActivityByNodeId(activityExecutionContextState.ScheduledActivityNodeId);
@@ -137,7 +137,7 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor
return null;
var properties = activityExecutionContextState.Properties;
- var activityExecutionContext = workflowExecutionContext.CreateActivityExecutionContext(activity);
+ var activityExecutionContext = await workflowExecutionContext.CreateActivityExecutionContext(activity);
activityExecutionContext.Id = activityExecutionContextState.Id;
activityExecutionContext.Properties = properties;
activityExecutionContext.ActivityState = activityExecutionContextState.ActivityState ?? new Dictionary();
diff --git a/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivity.cs b/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivity.cs
index 950ce04fc..5f7d2b1e2 100644
--- a/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivity.cs
+++ b/src/modules/Elsa.Workflows.Management/Activities/WorkflowDefinitionActivity/WorkflowDefinitionActivity.cs
@@ -45,7 +45,7 @@ public class WorkflowDefinitionActivity : Composite, IInitializable
///
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
{
- CopyInputOutputToVariables(context);
+ await CopyInputOutputToVariables(context);
await context.ScheduleActivityAsync(Root, OnChildCompletedAsync);
}
@@ -84,10 +84,10 @@ public class WorkflowDefinitionActivity : Composite, IInitializable
await activityExecutionContext.CompleteActivityAsync(completeCompositeSignal?.Value);
}
- private void CopyInputOutputToVariables(ActivityExecutionContext context)
+ private async Task CopyInputOutputToVariables(ActivityExecutionContext context)
{
var serviceProvider = context.GetRequiredService();
- var activityDescriptor = FindActivityDescriptor(serviceProvider);
+ var activityDescriptor = await FindActivityDescriptor(serviceProvider);
DeclareInputAsVariables(activityDescriptor, (descriptor, variable) =>
{
@@ -99,7 +99,7 @@ public class WorkflowDefinitionActivity : Composite, IInitializable
variable.Set(context, evaluatedExpression);
});
- DeclareOutputAsVariables(activityDescriptor, (descriptor, variable) => context.ExpressionExecutionContext.Memory.Declare(variable));
+ DeclareOutputAsVariables(activityDescriptor, (_, variable) => context.ExpressionExecutionContext.Memory.Declare(variable));
}
private void DeclareInputAsVariables(ActivityDescriptor activityDescriptor, Action configureVariable)
@@ -165,10 +165,10 @@ public class WorkflowDefinitionActivity : Composite, IInitializable
return workflowGraph;
}
- private ActivityDescriptor? FindActivityDescriptor(IServiceProvider serviceProvider)
+ private async Task FindActivityDescriptor(IServiceProvider serviceProvider)
{
- var activityRegistry = serviceProvider.GetRequiredService();
- return activityRegistry.Find(Type, Version) ?? activityRegistry.Find(Type);
+ var activityRegistryLookup = serviceProvider.GetRequiredService();
+ return await activityRegistryLookup.Find(Type, Version) ?? await activityRegistryLookup.Find(Type);
}
async ValueTask IInitializable.InitializeAsync(InitializationContext context)
@@ -186,7 +186,7 @@ public class WorkflowDefinitionActivity : Composite, IInitializable
if (workflowGraph == null)
throw new Exception($"Could not find workflow definition with ID {WorkflowDefinitionId}.");
- var activityDescriptor = FindActivityDescriptor(serviceProvider);
+ var activityDescriptor = await FindActivityDescriptor(serviceProvider);
if (activityDescriptor == null)
{
diff --git a/src/modules/Elsa.Workflows.Management/Services/ActivityRegistryPopulator.cs b/src/modules/Elsa.Workflows.Management/Services/ActivityRegistryPopulator.cs
index 5c47899f9..a7836f5ac 100644
--- a/src/modules/Elsa.Workflows.Management/Services/ActivityRegistryPopulator.cs
+++ b/src/modules/Elsa.Workflows.Management/Services/ActivityRegistryPopulator.cs
@@ -7,41 +7,18 @@ namespace Elsa.Workflows.Management.Services;
///
/// Populates the with descriptors provided by s.
///
-public class ActivityRegistryPopulator : IActivityRegistryPopulator
+public class ActivityRegistryPopulator(IEnumerable providers, IActivityRegistry registry) : IActivityRegistryPopulator
{
- private readonly IEnumerable _providers;
- private readonly IActivityRegistry _registry;
-
- ///
- /// Constructor.
- ///
- public ActivityRegistryPopulator(IEnumerable providers, IActivityRegistry registry)
- {
- _providers = providers;
- _registry = registry;
- }
-
///
public async Task PopulateRegistryAsync(CancellationToken cancellationToken)
{
- _registry.Clear();
-
- foreach (var provider in _providers)
- await PopulateRegistryAsync(provider, cancellationToken);
- }
-
- ///
- public async Task PopulateRegistryAsync(Type providerType, CancellationToken cancellationToken = default)
- {
- _registry.ClearProvider(providerType);
- var provider = _providers.First(x => x.GetType() == providerType);
- await PopulateRegistryAsync(provider, cancellationToken);
+ await registry.RefreshDescriptors(providers, cancellationToken);
}
///
public async Task AddToRegistry(Type providerType, string workflowDefinitionVersionId, CancellationToken cancellationToken = default)
{
- var provider = _providers.First(x => x.GetType() == providerType);
+ var provider = providers.First(x => x.GetType() == providerType);
var descriptors = await provider.GetDescriptorsAsync(cancellationToken);
var descriptorToAdd = descriptors
.SingleOrDefault(d =>
@@ -49,13 +26,13 @@ public class ActivityRegistryPopulator : IActivityRegistryPopulator
val.ToString() == workflowDefinitionVersionId);
if (descriptorToAdd is not null)
- _registry.Add(providerType, descriptorToAdd);
+ registry.Add(providerType, descriptorToAdd);
}
///
public void RemoveDefinitionFromRegistry(Type providerType, string workflowDefinitionId, CancellationToken cancellationToken = default)
{
- var providerDescriptors = _registry.ListByProvider(providerType);
+ var providerDescriptors = registry.ListByProvider(providerType);
var descriptorsToRemove = providerDescriptors
.Where(d =>
@@ -64,14 +41,14 @@ public class ActivityRegistryPopulator : IActivityRegistryPopulator
foreach (ActivityDescriptor activityDescriptor in descriptorsToRemove)
{
- _registry.Remove(providerType, activityDescriptor);
+ registry.Remove(providerType, activityDescriptor);
}
}
///
public void RemoveDefinitionVersionFromRegistry(Type providerType, string workflowDefinitionVersionId, CancellationToken cancellationToken = default)
{
- var providerDescriptors = _registry.ListByProvider(providerType);
+ var providerDescriptors = registry.ListByProvider(providerType);
var descriptorToRemove = providerDescriptors
.SingleOrDefault(d =>
@@ -79,12 +56,6 @@ public class ActivityRegistryPopulator : IActivityRegistryPopulator
val.ToString() == workflowDefinitionVersionId);
if (descriptorToRemove is not null)
- _registry.Remove(providerType, descriptorToRemove);
- }
-
- private async Task PopulateRegistryAsync(IActivityProvider provider, CancellationToken cancellationToken = default)
- {
- var descriptors = await provider.GetDescriptorsAsync(cancellationToken);
- _registry.AddMany(provider.GetType(), descriptors);
+ registry.Remove(providerType, descriptorToRemove);
}
}
\ No newline at end of file
diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/ScheduleActivityExecutionContextTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/ScheduleActivityExecutionContextTests.cs
index 3c7f48fd1..91a7258f0 100644
--- a/test/unit/Elsa.Workflows.Core.UnitTests/ScheduleActivityExecutionContextTests.cs
+++ b/test/unit/Elsa.Workflows.Core.UnitTests/ScheduleActivityExecutionContextTests.cs
@@ -23,7 +23,7 @@ public class ScheduleActivityExecutionContextTests(ITestOutputHelper testOutputH
var workflowGraphBuilder = _serviceProvider.GetRequiredService();
var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow);
var workflowExecutionContext = await WorkflowExecutionContext.CreateAsync(_serviceProvider, workflowGraph, "test");
- var activityExecutionContext = workflowExecutionContext.CreateActivityExecutionContext(writeLineA);
+ var activityExecutionContext = await workflowExecutionContext.CreateActivityExecutionContext(writeLineA);
await Assert.ThrowsAsync(() => activityExecutionContext.ScheduleActivityAsync(writeLineB).AsTask());
}