public static void Main() { var e1 = false; var e2 = false; var e3 = false; var model = ProcessModel.Create() .AddEventCatcher("start") .AddActivity("a1", () => { }) .AddActivity("c1", () => e1 = true) .AttachAsCompensationActivity("c1", "a1") .AddActivity("a2", () => throw new Exception()) .AddActivity("c2", () => e2 = true) .AttachAsCompensationActivity("c2", "a2") .AddActivity("a3", () => { }) .AddActivity("c3", () => e3 = true) .AttachAsCompensationActivity("c3", "a3") .AddEventThrower("end") .AddSequenceFlow("start", "a1", "a2", "a3", "end"); var models = new InMemoryProcessModelsStore(model); var instances = new InMemoryProcessInstancesStore(); var sc = new ServiceCollection(); sc.AddLogging(cfg => { cfg.AddConsole(); }); var manager = new ProcessManager(models, instances, sc.BuildServiceProvider()); var result = manager.HandleEvent(null).First(); var relatedInstance = manager.InstancesStore.GetById(result.ProcessInstanceId); }
public void ReturnTwoTokensWhenThereAreEventHandlersInBothPaths() { var model = ProcessModel.Create() .AddEventCatcher("start") .AddActivity("msgBefore", () => { }) .AddParallelGateway("split") .AddSequenceFlow("start", "msgBefore", "split") .AddActivity("msgLeft", () => { }) .AddEventCatcher("evtLeft") .AddActivity("msgRight", () => { }) .AddEventCatcher("evtRight") .AddParallelGateway("join") .AddSequenceFlow("split", "msgLeft", "evtLeft", "join") .AddSequenceFlow("split", "msgRight", "evtRight", "join") .AddActivity("msgAfter", () => { }) .AddEventThrower("end") .AddSequenceFlow("join", "msgAfter", "end"); var models = new InMemoryProcessModelsStore(model); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); var result = manager.HandleEvent(null); result.FirstOrDefault().AffectedTokens.Count().Should().Be(2); }
public void StartMiddleEnd() { var models = new InMemoryProcessModelsStore(); models.Store(ProcessModel.Create() .AddEventCatcher("start", TypedEventCatcher <Start> .Create()) .AddEventCatcher("middle", CatchAnyEventCatcher.Create()) .AddEventThrower("end", SilentEventThrower.Instance) .AddSequenceFlow("start", "middle", "end")); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); var result = manager.HandleEvent(new Start()).First(); manager.GetExecutionPoint( result.ProcessInstanceId, result.AffectedTokens.First() ).Should().Be("middle"); result = manager.HandleEvent(result.ProcessInstanceId, result.AffectedTokens.First(), new object()); manager.InstancesStore.GetById(result.ProcessInstanceId) .IsDone.Should().Be(true); }
public void WhenManualActivityFailsCompensationActivitiesRun() { var data = 0; var model = ProcessModel.Create() .AddAnyEventCatcher("start") .AddActivity("regular", () => data = 10) .AddActivity("compensation", () => data -= 5) .AttachAsCompensationActivity("compensation", "regular") .AddActivity <ManualActivity>("failing") .AddEventThrower("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); }
public void SimpleDecisionMakingProcess(bool data) { var output = false; var model = ProcessModel.Create() .AddEventCatcher("start") .AddExclusiveGateway("If") .AddActivity("True", () => output = true) .AddActivity("False", () => output = false) .AddExclusiveGateway("EndIf") .AddEventThrower("end") .AddSequenceFlow("start", "If") .AddConditionalSequenceFlow("If", "True", true) .AddConditionalSequenceFlow("If", "False", false) .AddSequenceFlow("True", "EndIf") .AddSequenceFlow("False", "EndIf") .AddSequenceFlow("EndIf", "end"); var models = new InMemoryProcessModelsStore(model); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); manager.HandleEvent(data); output.Should().Be(data); }
public void PauseTheExecutionOfTheProcess() { var model = ProcessModel.Create() .AddEventCatcher("start") .AddActivity("activity", new UserActivity()) .AddEventThrower("end") .AddSequenceFlow("start", "activity", "end"); var instances = new InMemoryProcessInstancesStore(); var models = new InMemoryProcessModelsStore(model); var manager = new ProcessManager(models, instances); var result = manager.HandleEvent(null).FirstOrDefault(); var instance = manager .InstancesStore .GetById(result.ProcessInstanceId); instance.IsDone.Should().BeFalse(); result = manager.HandleActivityCompletion( result.ProcessInstanceId, result.AffectedTokens.First(), null ); instance.IsDone.Should().BeTrue(); }
public void ThrowInvalidOperationExceptionWhenNonExistentInstanceIdIsInformedToHandleActivityCompletion() { var models = new InMemoryProcessModelsStore(); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); Action sut = () => manager.HandleActivityCompletion(Guid.NewGuid(), Guid.NewGuid(), null); sut.Should().Throw <InvalidOperationException>(); }
public void ReturnTheProcessInstancesStoreWhenRequested() { var models = new InMemoryProcessModelsStore(); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); manager.GetService <IProcessInstancesStore>() .Should().Be(instances); manager.GetService <IProcessInstanceProvider>() .Should().Be(instances); }
public void WhenTheProcessFailsCompensationActivitiesRun2() { var model = ProcessModel.Create() .AddAnyEventCatcher("start") .AddActivityWithCompensation <RegularActivity, CompensationActivity>() .AddActivity("failing", () => throw new Exception()) .AddEventThrower("end") .AddSequenceFlow("start", "Regular", "failing", "end"); var models = new InMemoryProcessModelsStore(model); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); manager.HandleEvent(null); SharedState.Should().Be(5); }
public void ThrowInvalidOperationExceptionWhenNonExistentModelIdIsInformedToHandleActivityCompletion() { var model = ProcessModel.CreateWithSingleActivity( new UserActivity() ); var models = new InMemoryProcessModelsStore(model); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); var result = manager.HandleEvent(null).First(); var manager2 = new ProcessManager( new InMemoryProcessModelsStore(), instances ); Action sut = () => manager2.HandleActivityCompletion(result.ProcessInstanceId, Guid.NewGuid(), null); sut.Should().Throw <InvalidOperationException>(); }
public void WhenTheProcessFailsCompensationActivitiesRun() { var data = 0; var model = ProcessModel.Create() .AddAnyEventCatcher("start") .AddActivity("regular", () => data = 10) .AddActivity("compensation", () => data -= 5) .AttachAsCompensationActivity("compensation", "regular") .AddActivity("failing", () => throw new Exception()) .AddEventThrower("end") .AddSequenceFlow("start", "regular", "failing", "end"); var models = new InMemoryProcessModelsStore(model); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); manager.HandleEvent(null); data.Should().Be(5); }
public void ReturnOneTokenWhenThereIsAnEventHandlerInOneOfThePaths() { var model = ProcessModel.Create() .AddEventCatcher("start") .AddActivity("msgBefore", () => { }) .AddParallelGateway("split") .AddSequenceFlow("start", "msgBefore", "split") .AddActivity("msgLeft", () => { }) .AddEventCatcher("evtLeft") .AddActivity("msgRight", () => { }) .AddParallelGateway("join") .AddSequenceFlow("split", "msgLeft", "evtLeft", "join") .AddSequenceFlow("split", "msgRight", "join") .AddActivity("msgAfter", () => { }) .AddEventThrower("end") .AddSequenceFlow("join", "msgAfter", "end"); var models = new InMemoryProcessModelsStore(model); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); var results = manager.HandleEvent(null).ToArray(); results.Length.Should().Be(1); var result = results[0]; var affectedTokens = result.AffectedTokens.ToArray(); affectedTokens.Length.Should().Be(1); result = manager .HandleEvent(result.ProcessInstanceId, affectedTokens[0], null); //.AffectedTokens. var instance = manager.InstancesStore.GetById(result.ProcessInstanceId); instance.IsDone.Should().BeTrue(); }
public void CreateInstancesOnlyWhenApplicable() { var model = ProcessModel.Create() .AddEventCatcher("start", TypedEventCatcher <Start> .Create()) .AddEventCatcher("middle", CatchAnyEventCatcher.Create()) .AddEventThrower("end", SilentEventThrower.Instance) .AddSequenceFlow("start", "middle", "end"); var models = new InMemoryProcessModelsStore(); models.Store(model); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); manager.HandleEvent(new object()); manager.InstancesStore.GetRunningInstancesCount().Should().Be(0); manager.HandleEvent(new Start()); manager.InstancesStore.GetRunningInstancesCount().Should().Be(1); }
public void ActivitiesRanInTheRightSequence() { var op = 1; var e0 = 0; var e1 = 0; var e2 = 0; var e3 = 0; var lockObject = new object(); var model = ProcessModel.Create() .AddEventCatcher("start") .AddActivity("msgBefore", () => { e0 = op++; }) // 0+1 .AddParallelGateway("split") .AddSequenceFlow("start", "msgBefore", "split") .AddActivity("msgLeft", () => { lock (lockObject) { e1 = op++; } }) // 1+2 .AddActivity("msgRight", () => { lock (lockObject) { e2 = op++; } }) // 3+3 .AddParallelGateway("join") .AddSequenceFlow("split", "msgLeft", "join") .AddSequenceFlow("split", "msgRight", "join") .AddActivity("msgAfter", () => { e3 = op++; }) // 6+4 .AddEventThrower("end") .AddSequenceFlow("join", "msgAfter", "end"); var models = new InMemoryProcessModelsStore(model); var instances = new InMemoryProcessInstancesStore(); var sc = new ServiceCollection(); sc.AddLogging(); sc.AddSingleton <IProcessMonitor, InMemoryProcessMonitor>(); var sp = sc.BuildServiceProvider(); var manager = new ProcessManager(models, instances, sp); manager.HandleEvent(null); (e0 + e1 + e2 + e3).Should().Be(10); }
public void UsingDataReceivedInStartEventInTheFollowingAction() { var input = "Hello World"; string output = null; var start = CatchAnyEventCatcher.Create(); start.SetEventDataOutput("o"); var activity = LambdaActivity.Create((la, ctx) => { var i = la.GetDataInputByName("i"); output = (string)i.GetCurrentValue(ctx, "middle"); }); activity.Inputs.Add("i"); var model = ProcessModel.Create() .AddEventCatcher("start", start) .AddActivity("middle", activity) .AddEventThrower("end", SilentEventThrower.Instance) .AddSequenceFlow("start", "middle", "end") .AddDataAssociation("startToMiddle", DataAssociation.Create("start", "o", "middle", "i")); var models = new InMemoryProcessModelsStore(); models.Store(model); var instances = new InMemoryProcessInstancesStore(); var pm = new ProcessManager(models, instances); pm.HandleEvent(input); output.Should().Be(input); }
public void WhenProcessFailCompensationsAreExecutedOnlyForActivitiesThatWerePerformed() { var e1 = false; var e2 = false; var e3 = false; var model = ProcessModel.Create() .AddAnyEventCatcher("start") .AddActivity("a1", () => { }) .AddActivity("c1", () => e1 = true) .AttachAsCompensationActivity("c1", "a1") .AddActivity("a2", () => throw new Exception()) .AddActivity("c2", () => e2 = true) .AttachAsCompensationActivity("c2", "a2") .AddActivity("a3", () => { }) .AddActivity("c3", () => e3 = true) .AttachAsCompensationActivity("c3", "a3") .AddEventThrower("end") .AddSequenceFlow("start", "a1", "a2", "a3", "end"); var models = new InMemoryProcessModelsStore(model); var instances = new InMemoryProcessInstancesStore(); var manager = new ProcessManager(models, instances); var result = manager.HandleEvent(null).First(); var relatedInstance = manager.InstancesStore.GetById(result.ProcessInstanceId); relatedInstance.WasActivityCompleted("a1").Should().BeTrue(); relatedInstance.WasActivityCompleted("a2").Should().BeFalse(); relatedInstance.WasActivityCompleted("a3").Should().BeFalse(); e1.Should().BeTrue(); e2.Should().BeFalse(); e3.Should().BeFalse(); }