Add support for providing workflow input via dispatch endpoint
This commit is contained in:
parent
2f8dde1f99
commit
d8b95db04e
|
|
@ -3,6 +3,7 @@ using Elsa.Expressions.Models;
|
|||
using Elsa.Extensions;
|
||||
using Elsa.JavaScript.Notifications;
|
||||
using Elsa.Mediator.Contracts;
|
||||
using Elsa.Workflows.Core.Contracts;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
using Elsa.Workflows.Management.Activities;
|
||||
using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity;
|
||||
|
|
@ -38,27 +39,41 @@ public class WorkflowDefinitionActivityJavaScriptHandler : INotificationHandler<
|
|||
var engine = notification.Engine;
|
||||
var context = notification.Context;
|
||||
|
||||
// If we are already evaluating inputs, then we're in a circular evaluation loop. In this case, we should not attempt to evaluate the inputs.
|
||||
if(context.TransientProperties.TryGetValue("EvaluatingInputs", out var evaluatingInputs) && (bool)evaluatingInputs)
|
||||
return;
|
||||
// Always create workflow input accessors.
|
||||
CreateWorkflowInputAccessors(engine, context);
|
||||
|
||||
// If we are already evaluating inputs, then we're in a circular evaluation loop. In this case, we should not attempt to evaluate the inputs.
|
||||
if (context.TransientProperties.TryGetValue("EvaluatingInputs", out var evaluatingInputs) && (bool)evaluatingInputs)
|
||||
return;
|
||||
|
||||
// To prevent a circular evaluation loop, set a flag on the context to indicate that we're currently evaluating the inputs.
|
||||
context.TransientProperties["EvaluatingInputs"] = true;
|
||||
|
||||
|
||||
// Create input getters.
|
||||
await CreateInputAccessorsAsync(engine, context);
|
||||
}
|
||||
|
||||
private void CreateWorkflowInputAccessors(Engine engine, ExpressionExecutionContext context)
|
||||
{
|
||||
var input = context.GetWorkflowExecutionContext().Input;
|
||||
|
||||
foreach (var inputEntry in input)
|
||||
{
|
||||
var inputPascalName = inputEntry.Key.Pascalize();
|
||||
var inputValue = inputEntry.Value;
|
||||
engine.SetValue($"get{inputPascalName}", (Func<object?>)(() => inputValue));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CreateInputAccessorsAsync(Engine engine, ExpressionExecutionContext context)
|
||||
{
|
||||
var workflowDefinitionActivity = GetFirstWorkflowDefinitionActivity(context);
|
||||
|
||||
var workflowDefinitionActivity = context.GetActivityExecutionContext().GetFirstWorkflowDefinitionActivity();
|
||||
if (workflowDefinitionActivity == null)
|
||||
return;
|
||||
|
||||
var descriptor = _activityRegistry.Find(workflowDefinitionActivity.Type, workflowDefinitionActivity.Version)!;
|
||||
var inputDefinitions = descriptor.Inputs;
|
||||
|
||||
var workflowDefinitionActivityDescriptor = _activityRegistry.Find(workflowDefinitionActivity.Type, workflowDefinitionActivity.Version);
|
||||
var inputDefinitions = workflowDefinitionActivityDescriptor?.Inputs ?? Enumerable.Empty<InputDescriptor>();
|
||||
|
||||
foreach (var inputDefinition in inputDefinitions)
|
||||
{
|
||||
var inputPascalName = inputDefinition.Name.Pascalize();
|
||||
|
|
@ -68,7 +83,4 @@ public class WorkflowDefinitionActivityJavaScriptHandler : INotificationHandler<
|
|||
engine.SetValue($"get{inputPascalName}", (Func<object?>)(() => evaluatedExpression));
|
||||
}
|
||||
}
|
||||
|
||||
private static WorkflowDefinitionActivity? GetFirstWorkflowDefinitionActivity(ExpressionExecutionContext context) =>
|
||||
context.GetActivityExecutionContext().GetFirstWorkflowDefinitionActivity();
|
||||
}
|
||||
|
|
@ -70,6 +70,7 @@ public class JintJavaScriptEvaluator : IJavaScriptEvaluator
|
|||
engine.SetValue("setCorrelationId", (Action<string?>)(value => context.GetActivityExecutionContext().WorkflowExecutionContext.CorrelationId = value));
|
||||
engine.SetValue("setVariable", (Action<string, object>)((name, value) => context.SetVariable(name, value)));
|
||||
engine.SetValue("getVariable", (Func<string, object?>)(name => context.GetVariable(name)));
|
||||
engine.SetValue("getInput", (Func<string, object?>)(name => context.GetWorkflowExecutionContext().Input.GetValue(name)));
|
||||
|
||||
// Create variable & input setters and getters for each variable.
|
||||
CreateMemoryBlockAccessors(engine, context);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ internal class CommonFunctionsDefinitionProvider : FunctionDefinitionProvider
|
|||
.Parameter("name", "string")
|
||||
.ReturnType("any"));
|
||||
|
||||
yield return CreateFunctionDefinition(builder => builder
|
||||
.Name("getInput")
|
||||
.Parameter("name", "string")
|
||||
.ReturnType("any"));
|
||||
|
||||
yield return CreateFunctionDefinition(builder => builder
|
||||
.Name("isNullOrWhiteSpace")
|
||||
.Parameter("value", "string")
|
||||
|
|
|
|||
|
|
@ -34,11 +34,15 @@ internal class Endpoint : ElsaEndpoint<Request, Response>
|
|||
await SendNotFoundAsync(cancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
var correlationId = request.CorrelationId;
|
||||
var input = (IDictionary<string, object>?)request.Input;
|
||||
|
||||
var result = await _workflowDispatcher.DispatchAsync(new DispatchWorkflowDefinitionRequest(
|
||||
await _workflowDispatcher.DispatchAsync(new DispatchWorkflowDefinitionRequest(
|
||||
request.DefinitionId,
|
||||
VersionOptions.Published,
|
||||
CorrelationId: request.CorrelationId),
|
||||
input,
|
||||
correlationId),
|
||||
cancellationToken);
|
||||
|
||||
await SendOkAsync(new Response(), cancellationToken);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
using System.Text.Json.Serialization;
|
||||
using Elsa.Workflows.Core.Serialization.Converters;
|
||||
|
||||
namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Dispatch;
|
||||
|
||||
public class Request
|
||||
internal class Request
|
||||
{
|
||||
public string DefinitionId { get; set; } = default!;
|
||||
public string? CorrelationId { get; set; }
|
||||
|
||||
[JsonConverter(typeof(ExpandoObjectConverter))]
|
||||
public object? Input { get; set; }
|
||||
}
|
||||
|
||||
public class Response
|
||||
internal class Response
|
||||
{
|
||||
}
|
||||
|
|
@ -2,9 +2,8 @@ using Elsa.Mediator.Contracts;
|
|||
using Elsa.Workflows.Management.Contracts;
|
||||
using Elsa.Workflows.Management.Entities;
|
||||
using Elsa.Workflows.Management.Notifications;
|
||||
using Elsa.Workflows.Management.Providers;
|
||||
|
||||
namespace Elsa.Workflows.Management.Handlers;
|
||||
namespace Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity;
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the <see cref="IActivityRegistry"/> for the <see cref="WorkflowDefinitionActivityProvider"/> provider whenever an <see cref="WorkflowDefinition"/> is published, retracted or deleted.
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
using Elsa.Common.Models;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
using Elsa.Workflows.Management.Activities;
|
||||
using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity;
|
||||
using Elsa.Workflows.Management.Contracts;
|
||||
using Elsa.Workflows.Management.Entities;
|
||||
using Humanizer;
|
||||
|
||||
namespace Elsa.Workflows.Management.Providers;
|
||||
namespace Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity;
|
||||
|
||||
/// <summary>
|
||||
/// Provides activity descriptors based on <see cref="WorkflowDefinition"/>s stored in the database.
|
||||
|
|
|
|||
Loading…
Reference in a new issue