Implement unwinding of Switch activity
This commit is contained in:
parent
a67f07ac70
commit
3f173d6468
|
|
@ -1,9 +1,14 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.ActivityResults;
|
||||
using Elsa.Attributes;
|
||||
using Elsa.Events;
|
||||
using Elsa.Services;
|
||||
using Elsa.Services.Models;
|
||||
using MediatR;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Elsa.Activities.ControlFlow
|
||||
|
|
@ -14,7 +19,7 @@ namespace Elsa.Activities.ControlFlow
|
|||
Description = "Evaluate multiple conditions and continue execution depending on the results.",
|
||||
Outcomes = new[] { OutcomeNames.Done }
|
||||
)]
|
||||
public class Switch : Activity
|
||||
public class Switch : Activity, INotificationHandler<ScopeEvicted>
|
||||
{
|
||||
[ActivityProperty(Hint = "The conditions to evaluate.")]
|
||||
public ICollection<SwitchCase> Cases { get; set; } = new List<SwitchCase>();
|
||||
|
|
@ -27,9 +32,29 @@ namespace Elsa.Activities.ControlFlow
|
|||
get => GetState<bool>();
|
||||
set => SetState(value);
|
||||
}
|
||||
|
||||
public bool EnteredScope
|
||||
{
|
||||
get => GetState<bool>();
|
||||
set => SetState(value);
|
||||
}
|
||||
|
||||
protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context)
|
||||
{
|
||||
if (!context.WorkflowInstance.Scopes.Contains(Id))
|
||||
{
|
||||
if (!EnteredScope)
|
||||
{
|
||||
context.WorkflowInstance.Scopes.Push(Id);
|
||||
EnteredScope = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnteredScope = false;
|
||||
return Done();
|
||||
}
|
||||
}
|
||||
|
||||
if (Evaluated)
|
||||
{
|
||||
Evaluated = false;
|
||||
|
|
@ -38,10 +63,21 @@ namespace Elsa.Activities.ControlFlow
|
|||
|
||||
var matches = Cases.Where(x => x.Condition).Select(x => x.Name).ToList();
|
||||
var results = Mode == SwitchMode.MatchFirst ? matches.Any() ? new[] { matches.First() } : new string[0] : matches.ToArray();
|
||||
var outcomes = new[] { OutcomeNames.Done }.Concat(results);
|
||||
var outcomes = results;
|
||||
|
||||
Evaluated = true;
|
||||
return Outcomes(outcomes);
|
||||
}
|
||||
|
||||
public Task Handle(ScopeEvicted notification, CancellationToken cancellationToken)
|
||||
{
|
||||
if (notification.EvictedScope.Type != nameof(Switch))
|
||||
return Task.CompletedTask;
|
||||
|
||||
var data = notification.WorkflowExecutionContext.WorkflowInstance.ActivityData.GetItem(notification.EvictedScope.Id, () => new JObject());
|
||||
data.SetState(nameof(EnteredScope), false);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,11 +34,15 @@ namespace Elsa.Services
|
|||
|
||||
if (IsReturningIfElse(activity))
|
||||
return false;
|
||||
|
||||
if (IsReturningSwitch(activity))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsReturningComposite(IActivity activity) => activity is CompositeActivity && activity.Data.GetState<bool>(nameof(CompositeActivity.IsScheduled));
|
||||
private bool IsReturningIfElse(IActivity activity) => activity is IfElse && activity.Data.GetState<bool>(nameof(IfElse.EnteredScope));
|
||||
private bool IsReturningSwitch(IActivity activity) => activity is Switch && activity.Data.GetState<bool>(nameof(Switch.EnteredScope));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue