Skip to content

Commit

Permalink
Manual Activity, Handling Failures through ProcessManager
Browse files Browse the repository at this point in the history
  • Loading branch information
ElemarJR committed Sep 6, 2018
1 parent 1ee91b0 commit b733471
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 12 deletions.
7 changes: 7 additions & 0 deletions src/TheFlow/CoreConcepts/ProcessModel.Add.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ public ProcessModel AddActivity<TActivity>()
return AddActivity(Conventions.Naming.ActivityName(typeof(TActivity).Name), activity);
}

public ProcessModel AddActivity<TActivity>(string name)
where TActivity : Activity
{
var activity = Activator.CreateInstance<TActivity>();
return AddActivity(name, activity);
}

public ProcessModel AddParallelGateway(string name)
=> AddElement(NamedProcessElement<ParallelGateway>.Create(name, new ParallelGateway()));

Expand Down
11 changes: 11 additions & 0 deletions src/TheFlow/Elements/Activities/ManualActivity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using TheFlow.CoreConcepts;

namespace TheFlow.Elements.Activities
{
public class ManualActivity : Activity
{
public override void Run(ExecutionContext context)
{
}
}
}
24 changes: 23 additions & 1 deletion src/TheFlow/ProcessManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,29 @@ Guid tokenId
object failureData
)
{
throw new NotImplementedException();
var instance = InstancesStore.GetById(processInstanceId);
if (instance == null)
{
throw new InvalidOperationException("Instance not found.");
}

var model = ModelsStore.GetById(Guid.Parse(instance.ProcessModelId));
if (model == null)
{
throw new InvalidOperationException("Instance process model not found.");
}

var context = new ExecutionContext(this, model, instance, instance.Token.FindById(tokenId), null);

var tokens = instance.HandleActivityFailure(context, failureData);

InstancesStore.Store(instance);

return new HandleResult(
Guid.Parse(model.Id),
Guid.Parse(instance.Id),
tokens.Select(token => token.Id).ToList()
);
}

public HandleResult HandleActivityCompletion(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using TheFlow.Infrastructure.Stores;
using Xunit;

namespace TheFlow.Tests.Functional
namespace TheFlow.Tests.Functional.Basics
{
public class DataCommunications
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using TheFlow.Infrastructure.Stores;
using Xunit;

namespace TheFlow.Tests.Functional
namespace TheFlow.Tests.Functional.Basics
{
public class HandlingEventsInSequence
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System;
using System.Diagnostics;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using TheFlow.CoreConcepts;
using TheFlow.Elements.Activities;
using TheFlow.Elements.Events;
using Xunit;

namespace TheFlow.Tests.Functional
namespace TheFlow.Tests.Functional.Basics
{
public class HelloWorld
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using TheFlow.Infrastructure.Stores;
using Xunit;

namespace TheFlow.Tests.Functional
namespace TheFlow.Tests.Functional.Basics
{
public class MakingSimpleDecisions
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using TheFlow.Infrastructure.Stores;
using Xunit;

namespace TheFlow.Tests.Functional
namespace TheFlow.Tests.Functional.Basics
{
public class RunningTwoPathsInParallel
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System;
using System.Data;
using System.Linq;
using FluentAssertions;
using TheFlow.CoreConcepts;
using TheFlow.Elements.Activities;
using TheFlow.Infrastructure.Stores;
using Xunit;

namespace TheFlow.Tests.Functional
namespace TheFlow.Tests.Functional.Basics
{
public class Transactions
{
Expand All @@ -32,6 +32,34 @@ public void WhenTheProcessFailsCompensationActivitiesRun()
data.Should().Be(5);
}

[Fact]
public void WhenManualActivityFailsCompensationActivitiesRun()
{
var data = 0;
var model = ProcessModel.Create()
.AddEventCatcher("start")
.AddActivity("regular", () => data = 10)
.AddActivity("compensation", () => data -= 5)
.AttachAsCompensationActivity("compensation", "regular")
.AddActivity<ManualActivity>("failing")
.AddEventCatcher("end")
.AddSequenceFlow("start", "regular", "failing", "end");

var models = new InMemoryProcessModelsStore(model);
var instances = new InMemoryProcessInstancesStore();

var manager = new ProcessManager(models, instances);

var result = manager.HandleEvent(null).First();

manager.HandleActivityFailure(
result.ProcessInstanceId,
result.AffectedTokens.First(),
null);

data.Should().Be(5);
}

[Fact]
public void WhenProcessFailCompensationsAreExecutedOnlyForActivitiesThatWerePerformed()
{
Expand Down
38 changes: 37 additions & 1 deletion test/TheFlow.Tests/Unit/ProcessManagerShould.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Linq;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using TheFlow.CoreConcepts;
using TheFlow.Elements.Activities;
using TheFlow.Elements.Events;
Expand Down Expand Up @@ -165,5 +164,42 @@ public void ThrowInvalidOperationExceptionWhenNonExistentModelIdIsInformedToHand

sut.Should().Throw<InvalidOperationException>();
}

[Fact]
public void HandlingAnEventThatContinuesWithAnotherEventReturnsAnToken()
{
var model = ProcessModel.Create()
.AddEventCatcher("OnStart")
.AddEventCatcher("OnEvt1")
.AddEventCatcher("OnEvt2")
.AddEventThrower("End")
.AddSequenceFlow("OnStart", "OnEvt1", "OnEvt2", "End");

var manager = new ProcessManager(
new InMemoryProcessModelsStore(model),
new InMemoryProcessInstancesStore()
);

var e = manager.HandleEvent(null).First();

var result = manager.HandleEvent(
e.ProcessInstanceId, e.AffectedTokens.First(), null
);

result.AffectedTokens.Should().ContainInOrder(e.AffectedTokens);
result.ProcessInstanceId.Should().Be(e.ProcessInstanceId);
}

[Fact]
public void ThrowInvalidOperationExceptionWhenTryingToHandleFailureOfNonExistentInstance()
{
var manager = new ProcessManager(
new InMemoryProcessModelsStore(),
new InMemoryProcessInstancesStore()
);

Action a = () => manager.HandleActivityFailure(Guid.NewGuid(), Guid.Empty, null);
a.Should().Throw<InvalidOperationException>();
}
}
}

0 comments on commit b733471

Please sign in to comment.