Update activity completion API
This commit is contained in:
parent
beedc471dc
commit
4def8b8a10
|
|
@ -36,6 +36,9 @@ public abstract class Container : Activity, IContainer
|
|||
|
||||
// Schedule children.
|
||||
await ScheduleChildrenAsync(context);
|
||||
|
||||
// Because we override ExecuteAsync, this activity will not automatically complete.
|
||||
// Instead, it's up to the derived classes to explicitly complete this activity.
|
||||
}
|
||||
|
||||
protected virtual async ValueTask OnChildActivityCompletedAsync(ActivityCompleted signal, SignalContext context)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ using System.ComponentModel;
|
|||
using Elsa.Attributes;
|
||||
using Elsa.Contracts;
|
||||
using Elsa.Models;
|
||||
using Elsa.Signals;
|
||||
|
||||
namespace Elsa.Activities;
|
||||
|
||||
|
|
@ -36,7 +35,7 @@ public class Sequence : Container
|
|||
|
||||
if (currentIndex >= childActivities.Count)
|
||||
{
|
||||
await context.SignalAsync(new ActivityCompleted());
|
||||
await context.CompleteActivityAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,13 +20,7 @@ public abstract class Activity : ISignalHandler
|
|||
protected virtual async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
Execute(context);
|
||||
await OnExecutedAsync(context);
|
||||
}
|
||||
|
||||
protected virtual async ValueTask OnExecutedAsync(ActivityExecutionContext context)
|
||||
{
|
||||
// By default, signal that the activity is completed.
|
||||
await context.SignalAsync(new ActivityCompleted());
|
||||
await CompleteAsync(context);
|
||||
}
|
||||
|
||||
protected virtual ValueTask OnSignalReceivedAsync(object signal, SignalContext context)
|
||||
|
|
@ -43,9 +37,17 @@ public abstract class Activity : ISignalHandler
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notify the sytem that this activity completed.
|
||||
/// </summary>
|
||||
protected async ValueTask CompleteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
await context.CompleteActivityAsync();
|
||||
}
|
||||
|
||||
protected void OnSignalReceived(Type signalType, Func<object, SignalContext, ValueTask> handler) => _signalHandlers.Add(new SignalHandlerRegistration(signalType, handler));
|
||||
protected void OnSignalReceived<T>(Func<T, SignalContext, ValueTask> handler) => OnSignalReceived(typeof(T), (signal, context) => handler((T)signal, context));
|
||||
|
||||
|
||||
protected void OnSignalReceived<T>(Action<T, SignalContext> handler)
|
||||
{
|
||||
OnSignalReceived<T>((signal, context) =>
|
||||
|
|
@ -55,8 +57,11 @@ public abstract class Activity : ISignalHandler
|
|||
});
|
||||
}
|
||||
|
||||
ValueTask IActivity.ExecuteAsync(ActivityExecutionContext context) => ExecuteAsync(context);
|
||||
|
||||
async ValueTask IActivity.ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
await ExecuteAsync(context);
|
||||
}
|
||||
|
||||
async ValueTask ISignalHandler.HandleSignalAsync(object signal, SignalContext context)
|
||||
{
|
||||
// Give derived activity a chance to do something with the signal.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System.Collections.ObjectModel;
|
|||
using System.Reflection;
|
||||
using Elsa.Activities;
|
||||
using Elsa.Contracts;
|
||||
using Elsa.Signals;
|
||||
|
||||
namespace Elsa.Models;
|
||||
|
||||
|
|
@ -190,6 +191,14 @@ public class ActivityExecutionContext
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly complete the current activity. This should only be called by activities that explicitly suppress automatic-completion.
|
||||
/// </summary>
|
||||
public async ValueTask CompleteActivityAsync()
|
||||
{
|
||||
await SignalAsync(new ActivityCompleted());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a flattened list of the current context's ancestors.
|
||||
|
|
|
|||
|
|
@ -55,7 +55,11 @@ public class ForEachWorkflowTests
|
|||
{
|
||||
Items = new Input<ICollection<string>>(_items),
|
||||
CurrentValue = currentItem,
|
||||
Body = new WriteLine(context => currentItem.Get(context))
|
||||
Body = new If(() => true)
|
||||
{
|
||||
Then = new Break(),
|
||||
Else = new WriteLine()
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,24 +16,48 @@ public class SequentialWorkflowTests
|
|||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly Workflow _workflow;
|
||||
|
||||
public SequentialWorkflowTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
var services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = services.GetRequiredService<IWorkflowRunner>();
|
||||
_workflow = new WorkflowDefinitionBuilder().BuildWorkflow(new SequentialWorkflow());
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Sequence completes only after its child activities complete")]
|
||||
|
||||
[Fact(DisplayName = "Sequence completes after its child activities complete")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _workflowRunner.RunAsync(_workflow);
|
||||
var workflow = new WorkflowDefinitionBuilder().BuildWorkflow(new SequentialWorkflow());
|
||||
await _workflowRunner.RunAsync(workflow);
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Line 1", "Line 2", "Line 3" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Sequence completes after its child sequence activity complete")]
|
||||
public async Task Test2()
|
||||
{
|
||||
var workflow = new WorkflowDefinitionBuilder().BuildWorkflow(new NestedSequentialWorkflow());
|
||||
await _workflowRunner.RunAsync(workflow);
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "Line 1", "Line 2", "Line 3", "End" }, lines);
|
||||
}
|
||||
|
||||
|
||||
private class SequentialWorkflow : IWorkflow
|
||||
{
|
||||
public void Build(IWorkflowDefinitionBuilder workflow)
|
||||
{
|
||||
workflow.WithRoot(new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Line 1"),
|
||||
new WriteLine("Line 2"),
|
||||
new WriteLine("Line 3")
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class NestedSequentialWorkflow : IWorkflow
|
||||
{
|
||||
public void Build(IWorkflowDefinitionBuilder workflow)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue