From be3e7ac707f54cd3a2f5780aff6e94496369170d Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 22 Nov 2022 12:36:32 +0100 Subject: [PATCH] Update Composite and remove completion callback --- .../Activities/Composite.cs | 67 +++++++++++++++---- .../Elsa.Samples.TelnyxIntegration/GetAge.cs | 5 +- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/modules/Elsa.Workflows.Core/Activities/Composite.cs b/src/modules/Elsa.Workflows.Core/Activities/Composite.cs index 6c9f047ec..ce42f19b1 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Composite.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Composite.cs @@ -1,5 +1,6 @@ using System.ComponentModel; using Elsa.Expressions.Models; +using Elsa.Workflows.Core.Activities.Flowchart.Models; using Elsa.Workflows.Core.Attributes; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services; @@ -10,14 +11,18 @@ namespace Elsa.Workflows.Core.Activities; /// /// Represents a composite activity that has a single activity. Like a workflow, but without workflow-level properties. /// -[Activity("Elsa", "Workflows", "Execute a root activity that you can configure yourself")] -public class Composite : ActivityBase +public abstract class Composite : ActivityBase { + /// + protected Composite() + { + OnSignalReceived(OnCompleteCompositeSignal); + } + /// /// The activity to schedule when this activity executes. /// [Port] - [Browsable(false)] public IActivity Root { get; set; } = new Sequence(); /// @@ -39,16 +44,38 @@ public class Composite : ActivityBase await OnCompletedAsync(context, childContext); await context.CompleteActivityAsync(); } + + /// + /// Completes this composite activity. + /// + protected async Task CompleteAsync(ActivityExecutionContext context, object? result = default) => await context.SendSignalAsync(new CompleteCompositeSignal(result)); + + /// + /// Completes this composite activity. + /// + protected async Task CompleteAsync(ActivityExecutionContext context, params string[] outcomes) => await CompleteAsync(context, new Outcomes(outcomes)); - protected virtual ValueTask OnCompletedAsync(ActivityExecutionContext context, ActivityExecutionContext childContext) + protected virtual ValueTask OnCompletedAsync(ActivityExecutionContext context, ActivityExecutionContext childContext) { OnCompleted(context, childContext); return new(); } - protected virtual void OnCompleted(ActivityExecutionContext context, ActivityExecutionContext childContext) + protected virtual void OnCompleted(ActivityExecutionContext context, ActivityExecutionContext childContext) { } + + private async ValueTask OnCompleteCompositeSignal(CompleteCompositeSignal signal, SignalContext context) + { + var activityExecutionContext = context.ReceiverActivityExecutionContext; + + // Remove the existing completed handler. + activityExecutionContext.WorkflowExecutionContext.PopCompletionCallback(activityExecutionContext, Root); + + // Complete this activity. + await activityExecutionContext.CompleteActivityAsync(signal.Result); + context.StopPropagation(); + } protected static Inline From(Func activity) => new(activity); protected static Inline From(Func activity) => new(activity); @@ -82,7 +109,7 @@ public class Composite : ActivityBase ConfigureActivities(context); context.ScheduleActivity(Root, OnRootCompletedAsync); } - + /// /// Override this method to configure activity properties before execution. /// @@ -106,6 +133,28 @@ public class Composite : ActivityBase { } + /// + /// Completes this composite activity. + /// + protected async Task CompleteAsync(ActivityExecutionContext context, object? result = default) => await context.SendSignalAsync(new CompleteCompositeSignal(result)); + + /// + /// Completes this composite activity. + /// + protected async Task CompleteAsync(ActivityExecutionContext context, params string[] outcomes) => await CompleteAsync(context, new Outcomes(outcomes)); + + private async ValueTask OnCompleteCompositeSignal(CompleteCompositeSignal signal, SignalContext context) + { + var activityExecutionContext = context.ReceiverActivityExecutionContext; + + // Remove the existing completed handler. + activityExecutionContext.WorkflowExecutionContext.PopCompletionCallback(activityExecutionContext, Root); + + // Complete this activity. + await activityExecutionContext.CompleteActivityAsync(signal.Result); + context.StopPropagation(); + } + protected static Inline From(Func activity) => new(activity); protected static Inline From(Func activity) => new(activity); protected static Inline From(Action activity) => new(activity); @@ -114,10 +163,4 @@ public class Composite : ActivityBase protected static Inline From(Func> activity, MemoryBlockReference? output = default) => new(activity, output); protected static Inline From(Func activity, MemoryBlockReference? output = default) => new(activity, output); protected static Inline From(Func activity, MemoryBlockReference? output = default) => new(activity, output); - - private async ValueTask OnCompleteCompositeSignal(CompleteCompositeSignal signal, SignalContext context) - { - await context.ReceiverActivityExecutionContext.CompleteActivityAsync(signal.Result); - context.StopPropagation(); - } } \ No newline at end of file diff --git a/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/GetAge.cs b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/GetAge.cs index 734f40785..708103123 100644 --- a/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/GetAge.cs +++ b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/GetAge.cs @@ -1,8 +1,5 @@ -using Elsa.Workflows.Core; using Elsa.Workflows.Core.Activities; using Elsa.Workflows.Core.Activities.Flowchart.Attributes; -using Elsa.Workflows.Core.Activities.Flowchart.Models; -using Elsa.Workflows.Core.Signals; namespace Elsa.Samples.TelnyxIntegration; @@ -16,7 +13,7 @@ public class GetAge : Composite var random = new Random(); var n = random.Next(2); var outcome = n == 0 ? "Under 18" : "Over 18"; - await context.SendSignalAsync(new CompleteCompositeSignal(new Outcomes(outcome))); + await CompleteAsync(context, outcome); }); } } \ No newline at end of file