Improved support for named workflow instances
Introduced the ability to set and persist custom names for workflow instances. Updated relevant classes, services, and tests to ensure proper handling of the `Name` property.
This commit is contained in:
parent
b2d3fd9fda
commit
046b88f5d2
|
|
@ -1,4 +1,5 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Attributes;
|
||||
using Elsa.Workflows.Models;
|
||||
using JetBrains.Annotations;
|
||||
|
|
@ -12,18 +13,13 @@ namespace Elsa.Workflows.Activities;
|
|||
[PublicAPI]
|
||||
public class SetName : CodeActivity
|
||||
{
|
||||
/// <summary>
|
||||
/// The property key name used to store the workflow instance name.
|
||||
/// </summary>
|
||||
public const string WorkflowInstanceNameKey = "WorkflowInstanceName";
|
||||
|
||||
/// <inheritdoc />
|
||||
public SetName([CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line)
|
||||
public SetName([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public SetName(Input<string> value, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : this(source, line)
|
||||
public SetName(Input<string> value, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(source, line)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
|
@ -36,7 +32,7 @@ public class SetName : CodeActivity
|
|||
/// <inheritdoc />
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
var value = context.Get(Value);
|
||||
context.WorkflowExecutionContext.SetProperty(WorkflowInstanceNameKey, value!);
|
||||
var value = Value.GetOrDefault(context);
|
||||
context.WorkflowExecutionContext.Name = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -71,8 +71,8 @@ public partial class WorkflowExecutionContext : IExecutionContext
|
|||
_activityExecutionContexts = new List<ActivityExecutionContext>();
|
||||
Scheduler = serviceProvider.GetRequiredService<IActivitySchedulerFactory>().CreateScheduler();
|
||||
IdentityGenerator = serviceProvider.GetRequiredService<IIdentityGenerator>();
|
||||
Input = input != null ? new Dictionary<string, object>(input, StringComparer.OrdinalIgnoreCase) : new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
Properties = properties != null ? new Dictionary<string, object>(properties, StringComparer.OrdinalIgnoreCase) : new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
Input = input != null ? new(input, StringComparer.OrdinalIgnoreCase) : new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
Properties = properties != null ? new(properties, StringComparer.OrdinalIgnoreCase) : new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
ExecuteDelegate = executeDelegate;
|
||||
TriggerActivityId = triggerActivityId;
|
||||
CreatedAt = createdAt;
|
||||
|
|
@ -193,7 +193,7 @@ public partial class WorkflowExecutionContext : IExecutionContext
|
|||
MemoryRegister = workflowGraph.Workflow.CreateRegister()
|
||||
};
|
||||
|
||||
workflowExecutionContext.ExpressionExecutionContext = new ExpressionExecutionContext(serviceProvider, workflowExecutionContext.MemoryRegister, cancellationToken: cancellationToken);
|
||||
workflowExecutionContext.ExpressionExecutionContext = new(serviceProvider, workflowExecutionContext.MemoryRegister, cancellationToken: cancellationToken);
|
||||
|
||||
await workflowExecutionContext.SetWorkflowGraphAsync(workflowGraph);
|
||||
return workflowExecutionContext;
|
||||
|
|
@ -253,6 +253,9 @@ public partial class WorkflowExecutionContext : IExecutionContext
|
|||
/// An application-specific identifier associated with the execution context.
|
||||
public string? CorrelationId { get; set; }
|
||||
|
||||
/// Gets or sets the name of the workflow instance.
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// The ID of the workflow instance that triggered this instance.
|
||||
public string? ParentWorkflowInstanceId { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ public class JsonWorkflowStateSerializer : ConfigurableSerializer, IWorkflowStat
|
|||
public override JsonSerializerOptions GetOptions()
|
||||
{
|
||||
var options = base.GetOptions();
|
||||
return new JsonSerializerOptions(options)
|
||||
return new(options)
|
||||
{
|
||||
ReferenceHandler = new CrossScopedReferenceHandler()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ public class WorkflowRunner(
|
|||
: IWorkflowRunner
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<RunWorkflowResult> RunAsync(IActivity activity, RunWorkflowOptions? options = default, CancellationToken cancellationToken = default)
|
||||
public async Task<RunWorkflowResult> RunAsync(IActivity activity, RunWorkflowOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var workflow = Workflow.FromActivity(activity);
|
||||
var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow, cancellationToken);
|
||||
|
|
@ -33,7 +33,7 @@ public class WorkflowRunner(
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<RunWorkflowResult> RunAsync(IWorkflow workflow, RunWorkflowOptions? options = default, CancellationToken cancellationToken = default)
|
||||
public async Task<RunWorkflowResult> RunAsync(IWorkflow workflow, RunWorkflowOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var builder = workflowBuilderFactory.CreateBuilder();
|
||||
var workflowDefinition = await builder.BuildWorkflowAsync(workflow, cancellationToken);
|
||||
|
|
@ -41,14 +41,14 @@ public class WorkflowRunner(
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<RunWorkflowResult<TResult>> RunAsync<TResult>(WorkflowBase<TResult> workflow, RunWorkflowOptions? options = default, CancellationToken cancellationToken = default)
|
||||
public async Task<RunWorkflowResult<TResult>> RunAsync<TResult>(WorkflowBase<TResult> workflow, RunWorkflowOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var result = await RunAsync((IWorkflow)workflow, options, cancellationToken);
|
||||
return new(result.WorkflowState, result.Workflow, (TResult)result.Result!);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<RunWorkflowResult> RunAsync<T>(RunWorkflowOptions? options = default, CancellationToken cancellationToken = default) where T : IWorkflow, new()
|
||||
public async Task<RunWorkflowResult> RunAsync<T>(RunWorkflowOptions? options = null, CancellationToken cancellationToken = default) where T : IWorkflow, new()
|
||||
{
|
||||
var builder = workflowBuilderFactory.CreateBuilder();
|
||||
var workflowDefinition = await builder.BuildWorkflowAsync<T>(cancellationToken);
|
||||
|
|
@ -56,7 +56,7 @@ public class WorkflowRunner(
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<TResult> RunAsync<T, TResult>(RunWorkflowOptions? options = default, CancellationToken cancellationToken = default) where T : WorkflowBase<TResult>, new()
|
||||
public async Task<TResult> RunAsync<T, TResult>(RunWorkflowOptions? options = null, CancellationToken cancellationToken = default) where T : WorkflowBase<TResult>, new()
|
||||
{
|
||||
var builder = workflowBuilderFactory.CreateBuilder();
|
||||
var workflow = await builder.BuildWorkflowAsync<T>(cancellationToken);
|
||||
|
|
@ -65,7 +65,7 @@ public class WorkflowRunner(
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<RunWorkflowResult> RunAsync(WorkflowGraph workflowGraph, RunWorkflowOptions? options = default, CancellationToken cancellationToken = default)
|
||||
public async Task<RunWorkflowResult> RunAsync(WorkflowGraph workflowGraph, RunWorkflowOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Set up a workflow execution context.
|
||||
var instanceId = options?.WorkflowInstanceId ?? identityGenerator.GenerateId();
|
||||
|
|
@ -82,7 +82,7 @@ public class WorkflowRunner(
|
|||
parentWorkflowInstanceId,
|
||||
input,
|
||||
properties,
|
||||
default,
|
||||
null,
|
||||
triggerActivityId,
|
||||
cancellationToken);
|
||||
|
||||
|
|
@ -93,21 +93,21 @@ public class WorkflowRunner(
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<RunWorkflowResult> RunAsync(Workflow workflow, RunWorkflowOptions? options = default, CancellationToken cancellationToken = default)
|
||||
public async Task<RunWorkflowResult> RunAsync(Workflow workflow, RunWorkflowOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow, cancellationToken);
|
||||
return await RunAsync(workflowGraph, options, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<RunWorkflowResult> RunAsync(Workflow workflow, WorkflowState workflowState, RunWorkflowOptions? options = default, CancellationToken cancellationToken = default)
|
||||
public async Task<RunWorkflowResult> RunAsync(Workflow workflow, WorkflowState workflowState, RunWorkflowOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow, cancellationToken);
|
||||
return await RunAsync(workflowGraph, workflowState, options, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<RunWorkflowResult> RunAsync(WorkflowGraph workflowGraph, WorkflowState workflowState, RunWorkflowOptions? options = default, CancellationToken cancellationToken = default)
|
||||
public async Task<RunWorkflowResult> RunAsync(WorkflowGraph workflowGraph, WorkflowState workflowState, RunWorkflowOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Create a workflow execution context.
|
||||
var input = options?.Input;
|
||||
|
|
@ -123,7 +123,7 @@ public class WorkflowRunner(
|
|||
parentWorkflowInstanceId,
|
||||
input,
|
||||
properties,
|
||||
default,
|
||||
null,
|
||||
triggerActivityId,
|
||||
cancellationToken);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor
|
|||
DefinitionVersionId = workflowExecutionContext.Workflow.Identity.Id,
|
||||
DefinitionVersion = workflowExecutionContext.Workflow.Identity.Version,
|
||||
CorrelationId = workflowExecutionContext.CorrelationId,
|
||||
Name = workflowExecutionContext.Name,
|
||||
ParentWorkflowInstanceId = workflowExecutionContext.ParentWorkflowInstanceId,
|
||||
Status = workflowExecutionContext.Status,
|
||||
SubStatus = workflowExecutionContext.SubStatus,
|
||||
|
|
@ -45,6 +46,7 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor
|
|||
{
|
||||
workflowExecutionContext.Id = state.Id;
|
||||
workflowExecutionContext.CorrelationId = state.CorrelationId;
|
||||
workflowExecutionContext.Name = state.Name;
|
||||
workflowExecutionContext.ParentWorkflowInstanceId = state.ParentWorkflowInstanceId;
|
||||
workflowExecutionContext.SubStatus = state.SubStatus;
|
||||
workflowExecutionContext.Bookmarks = state.Bookmarks;
|
||||
|
|
|
|||
|
|
@ -11,17 +11,17 @@ public class WorkflowState
|
|||
/// <summary>
|
||||
/// Gets or sets the ID.
|
||||
/// </summary>
|
||||
public string Id { get; set; } = default!;
|
||||
public string Id { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The workflow definition ID.
|
||||
/// </summary>
|
||||
public string DefinitionId { get; set; } = default!;
|
||||
public string DefinitionId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The workflow definition version ID.
|
||||
/// </summary>
|
||||
public string DefinitionVersionId { get; set; } = default!;
|
||||
public string DefinitionVersionId { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The workflow definition version.
|
||||
|
|
@ -37,6 +37,11 @@ public class WorkflowState
|
|||
/// The correlation ID of the workflow, if any.
|
||||
/// </summary>
|
||||
public string? CorrelationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the workflow instance.
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The status of the workflow.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Management.Entities;
|
||||
using Elsa.Workflows.State;
|
||||
|
||||
|
|
@ -16,14 +14,14 @@ public class WorkflowStateMapper
|
|||
public WorkflowInstance? Map(WorkflowState? source)
|
||||
{
|
||||
if (source == null)
|
||||
return default;
|
||||
return null;
|
||||
|
||||
var workflowInstance = new WorkflowInstance();
|
||||
Apply(source, workflowInstance);
|
||||
|
||||
return workflowInstance;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Maps a workflow state to a workflow instance.
|
||||
/// </summary>
|
||||
|
|
@ -38,14 +36,12 @@ public class WorkflowStateMapper
|
|||
target.Status = source.Status;
|
||||
target.SubStatus = source.SubStatus;
|
||||
target.CorrelationId = source.CorrelationId;
|
||||
target.Name = source.Name;
|
||||
target.IncidentCount = source.Incidents.Count;
|
||||
target.IsSystem = source.IsSystem;
|
||||
target.UpdatedAt = source.UpdatedAt;
|
||||
target.FinishedAt = source.FinishedAt;
|
||||
target.WorkflowState = source;
|
||||
|
||||
if (source.Properties.TryGetValue<string>(SetName.WorkflowInstanceNameKey, out var name))
|
||||
target.Name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -54,7 +50,7 @@ public class WorkflowStateMapper
|
|||
public WorkflowState? Map(WorkflowInstance? source)
|
||||
{
|
||||
if (source == null)
|
||||
return default;
|
||||
return null;
|
||||
|
||||
var workflowState = source.WorkflowState;
|
||||
workflowState.Id = source.Id;
|
||||
|
|
@ -66,13 +62,11 @@ public class WorkflowStateMapper
|
|||
workflowState.Status = source.Status;
|
||||
workflowState.SubStatus = source.SubStatus;
|
||||
workflowState.CorrelationId = source.CorrelationId;
|
||||
workflowState.Name = source.Name;
|
||||
workflowState.UpdatedAt = source.UpdatedAt;
|
||||
workflowState.FinishedAt = source.FinishedAt;
|
||||
workflowState.IsSystem = source.IsSystem;
|
||||
|
||||
if (source.Name != null)
|
||||
workflowState.Properties[SetName.WorkflowInstanceNameKey] = source.Name;
|
||||
|
||||
return workflowState;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,11 @@ public class WorkflowInstanceOptions
|
|||
/// </summary>
|
||||
public string? CorrelationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the workflow instance.
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The input to the workflow instance, if any.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -14,13 +14,14 @@ public class WorkflowInstanceFactory(IIdentityGenerator identityGenerator, ISyst
|
|||
public WorkflowState CreateWorkflowState(Workflow workflow, WorkflowInstanceOptions? options = null)
|
||||
{
|
||||
var now = systemClock.UtcNow;
|
||||
return new WorkflowState
|
||||
return new()
|
||||
{
|
||||
Id = string.IsNullOrEmpty(options?.WorkflowInstanceId) ? identityGenerator.GenerateId() : options.WorkflowInstanceId,
|
||||
DefinitionId = workflow.Identity.DefinitionId,
|
||||
DefinitionVersionId = workflow.Identity.Id,
|
||||
DefinitionVersion = workflow.Identity.Version,
|
||||
CorrelationId = options?.CorrelationId,
|
||||
Name = options?.Name,
|
||||
Input = options?.Input ?? new Dictionary<string, object>(),
|
||||
Properties = options?.Properties ?? new Dictionary<string, object>(),
|
||||
Status = WorkflowStatus.Running,
|
||||
|
|
@ -36,7 +37,7 @@ public class WorkflowInstanceFactory(IIdentityGenerator identityGenerator, ISyst
|
|||
public WorkflowInstance CreateWorkflowInstance(Workflow workflow, WorkflowInstanceOptions? options = null)
|
||||
{
|
||||
var workflowState = CreateWorkflowState(workflow, options);
|
||||
return new WorkflowInstance
|
||||
return new()
|
||||
{
|
||||
Id = workflowState.Id,
|
||||
ParentWorkflowInstanceId = workflowState.ParentWorkflowInstanceId,
|
||||
|
|
@ -45,6 +46,7 @@ public class WorkflowInstanceFactory(IIdentityGenerator identityGenerator, ISyst
|
|||
DefinitionVersionId = workflowState.DefinitionVersionId,
|
||||
Version = workflowState.DefinitionVersion,
|
||||
CorrelationId = workflowState.CorrelationId,
|
||||
Name = workflowState.Name,
|
||||
Status = workflowState.Status,
|
||||
SubStatus = workflowState.SubStatus,
|
||||
IncidentCount = workflowState.Incidents.Count,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public class CreateAndRunWorkflowInstanceRequestMapper(WorkflowDefinitionHandleM
|
|||
WorkflowDefinitionHandle = workflowDefinitionHandleMapper.Map(source.WorkflowDefinitionHandle),
|
||||
WorkflowInstanceId = workflowInstanceId.EmptyIfNull(),
|
||||
CorrelationId = source.CorrelationId.EmptyIfNull(),
|
||||
Name = source.Name.EmptyIfNull(),
|
||||
ParentId = source.ParentId.EmptyIfNull(),
|
||||
Input = source.Input?.SerializeInput() ?? new ProtoInput(),
|
||||
Properties = source.Properties?.SerializeProperties() ?? new ProtoProperties(),
|
||||
|
|
@ -41,8 +42,9 @@ public class CreateAndRunWorkflowInstanceRequestMapper(WorkflowDefinitionHandleM
|
|||
return new()
|
||||
{
|
||||
WorkflowDefinitionHandle = workflowDefinitionHandleMapper.Map(source.WorkflowDefinitionHandle),
|
||||
CorrelationId = source.CorrelationId,
|
||||
ParentId = source.ParentId,
|
||||
CorrelationId = source.CorrelationId.NullIfEmpty(),
|
||||
Name = source.Name.NullIfEmpty(),
|
||||
ParentId = source.ParentId.NullIfEmpty(),
|
||||
Input = source.Input?.DeserializeInput(),
|
||||
Properties = source.Properties?.DeserializeProperties(),
|
||||
ActivityHandle = activityHandleMapper.Map(source.ActivityHandle),
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ public class CreateWorkflowInstanceRequestMapper(WorkflowDefinitionHandleMapper
|
|||
WorkflowDefinitionHandle = workflowDefinitionHandleMapper.Map(source.WorkflowDefinitionHandle),
|
||||
WorkflowInstanceId = workflowInstanceId,
|
||||
CorrelationId = source.CorrelationId.EmptyIfNull(),
|
||||
Name = source.Name.EmptyIfNull(),
|
||||
ParentId = source.ParentId.EmptyIfNull(),
|
||||
Input = source.Input?.SerializeInput() ?? new ProtoInput(),
|
||||
Properties = source.Properties?.SerializeProperties() ?? new ProtoProperties()
|
||||
|
|
@ -40,8 +41,9 @@ public class CreateWorkflowInstanceRequestMapper(WorkflowDefinitionHandleMapper
|
|||
return new()
|
||||
{
|
||||
WorkflowDefinitionHandle = workflowDefinitionHandleMapper.Map(source.WorkflowDefinitionHandle),
|
||||
CorrelationId = source.CorrelationId,
|
||||
ParentId = source.ParentId,
|
||||
CorrelationId = source.CorrelationId.NullIfEmpty(),
|
||||
Name = source.Name.NullIfEmpty(),
|
||||
ParentId = source.ParentId.NullIfEmpty(),
|
||||
Input = source.Input?.DeserializeInput(),
|
||||
Properties = source.Properties?.DeserializeProperties()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -45,9 +45,10 @@ message CreateWorkflowInstanceRequest{
|
|||
WorkflowDefinitionHandle WorkflowDefinitionHandle = 1;
|
||||
string WorkflowInstanceId = 2;
|
||||
optional string CorrelationId = 3;
|
||||
optional string ParentId = 4;
|
||||
optional Input input = 5;
|
||||
optional Properties properties = 6;
|
||||
optional string Name = 4;
|
||||
optional string ParentId = 5;
|
||||
optional Input input = 6;
|
||||
optional Properties properties = 7;
|
||||
}
|
||||
|
||||
message CreateWorkflowInstanceResponse{
|
||||
|
|
@ -71,11 +72,12 @@ message CreateAndRunWorkflowInstanceRequest{
|
|||
WorkflowDefinitionHandle WorkflowDefinitionHandle = 1;
|
||||
string WorkflowInstanceId = 2;
|
||||
optional string CorrelationId = 3;
|
||||
optional string ParentId = 4;
|
||||
optional Input input = 5;
|
||||
optional Properties properties = 6;
|
||||
optional ActivityHandle ActivityHandle = 7;
|
||||
optional string TriggerActivityId = 8;
|
||||
optional string Name = 4;
|
||||
optional string ParentId = 5;
|
||||
optional Input input = 6;
|
||||
optional Properties properties = 7;
|
||||
optional ActivityHandle ActivityHandle = 8;
|
||||
optional string TriggerActivityId = 9;
|
||||
}
|
||||
|
||||
message ExportWorkflowStateResponse {
|
||||
|
|
|
|||
|
|
@ -12,12 +12,17 @@ public class CreateAndRunWorkflowInstanceRequest
|
|||
/// <summary>
|
||||
/// The ID of the workflow definition version to create an instance of.
|
||||
/// </summary>
|
||||
public WorkflowDefinitionHandle WorkflowDefinitionHandle { get; set; } = default!;
|
||||
public WorkflowDefinitionHandle WorkflowDefinitionHandle { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The correlation ID of the workflow, if any.
|
||||
/// </summary>
|
||||
public string? CorrelationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the workflow instance to be created.
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The input to the workflow instance, if any.
|
||||
|
|
|
|||
|
|
@ -12,13 +12,18 @@ public class CreateWorkflowInstanceRequest
|
|||
/// <summary>
|
||||
/// The ID of the workflow definition version to create an instance of.
|
||||
/// </summary>
|
||||
public WorkflowDefinitionHandle WorkflowDefinitionHandle { get; set; } = default!;
|
||||
public WorkflowDefinitionHandle WorkflowDefinitionHandle { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The correlation ID of the workflow, if any.
|
||||
/// </summary>
|
||||
public string? CorrelationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the workflow instance to be created.
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The input to the workflow instance, if any.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public class LocalWorkflowClient(
|
|||
{
|
||||
WorkflowInstanceId = WorkflowInstanceId,
|
||||
CorrelationId = request.CorrelationId,
|
||||
Name = request.Name,
|
||||
ParentWorkflowInstanceId = request.ParentId,
|
||||
Input = request.Input,
|
||||
Properties = request.Properties
|
||||
|
|
@ -58,6 +59,7 @@ public class LocalWorkflowClient(
|
|||
{
|
||||
Properties = request.Properties,
|
||||
CorrelationId = request.CorrelationId,
|
||||
Name = request.Name,
|
||||
Input = request.Input,
|
||||
WorkflowDefinitionHandle = request.WorkflowDefinitionHandle,
|
||||
ParentId = request.ParentId
|
||||
|
|
@ -148,6 +150,7 @@ public class LocalWorkflowClient(
|
|||
{
|
||||
WorkflowInstanceId = WorkflowInstanceId,
|
||||
CorrelationId = request.CorrelationId,
|
||||
Name = request.Name,
|
||||
ParentWorkflowInstanceId = request.ParentId,
|
||||
Input = request.Input,
|
||||
Properties = request.Properties
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@ public class SetNameTests
|
|||
_serviceProvider = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "WriteLine prints the expected line to the console.")]
|
||||
[Fact(DisplayName = "SetName sets the workflow instance name.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
const string expectedName = "Foo";
|
||||
var setName = new SetName(new Input<string>(expectedName));
|
||||
var result = await _serviceProvider.RunActivityAsync(setName);
|
||||
var actualName = result.WorkflowState.Properties[SetName.WorkflowInstanceNameKey];
|
||||
var actualName = result.WorkflowState.Name;
|
||||
Assert.Equal(expectedName, actualName);
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ public class DefaultRuntimeTests
|
|||
|
||||
const string workflowDefinitionId = nameof(SimpleSuspendedWorkflow);
|
||||
var workflowClient = await _workflowRuntime.CreateClientAsync();
|
||||
await workflowClient.CreateInstanceAsync(new CreateWorkflowInstanceRequest
|
||||
await workflowClient.CreateInstanceAsync(new()
|
||||
{
|
||||
WorkflowDefinitionHandle = WorkflowDefinitionHandle.ByDefinitionId(workflowDefinitionId, VersionOptions.Published)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
using Elsa.Common.Models;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.WorkflowInstanceName.Workflows;
|
||||
using Elsa.Workflows.Models;
|
||||
using Elsa.Workflows.Runtime;
|
||||
using Elsa.Workflows.Runtime.Messages;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.WorkflowInstanceName;
|
||||
|
||||
public class WorkflowInstanceNameTests
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IWorkflowRuntime _workflowRuntime;
|
||||
|
||||
public WorkflowInstanceNameTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.AddWorkflow<NamedWorkflow>()
|
||||
.Build();
|
||||
|
||||
_workflowRuntime = _services.GetRequiredService<IWorkflowRuntime>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Setting a workflow instance name keeps the workflow instance name when the workflow is executed")]
|
||||
public async Task SuspendedCancelTest()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
const string workflowDefinitionId = nameof(NamedWorkflow);
|
||||
var desiredName = Guid.NewGuid().ToString();
|
||||
var workflowClient = await _workflowRuntime.CreateClientAsync();
|
||||
await workflowClient.CreateInstanceAsync(new()
|
||||
{
|
||||
Name = desiredName,
|
||||
WorkflowDefinitionHandle = WorkflowDefinitionHandle.ByDefinitionId(workflowDefinitionId, VersionOptions.Published)
|
||||
});
|
||||
await workflowClient.RunInstanceAsync(RunWorkflowInstanceRequest.Empty);
|
||||
var workflowState = await workflowClient.ExportStateAsync();
|
||||
|
||||
Assert.Equal([desiredName], _capturingTextWriter.Lines);
|
||||
Assert.Equal(desiredName, workflowState.Name);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.WorkflowInstanceName.Workflows;
|
||||
|
||||
public class NamedWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
builder.Root = new WriteLine(x => x.GetWorkflowExecutionContext().Name);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue