Implement unwinding of Switch activity

This commit is contained in:
Sipke Schoorstra 2021-02-17 21:43:16 +01:00
parent a67f07ac70
commit 3f173d6468
2 changed files with 42 additions and 2 deletions

View file

@ -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;
}
}
}

View file

@ -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));
}
}