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 UpdateTheDataInputCurrentValue() { var output = new DataOutput("a"); var element1 = new NullElement(); element1.Outputs.Add(output); var input = new DataInput("a"); var element2 = new NullElement(); element2.Inputs.Add(input); var model = ProcessModel.Create() .AddNullElement("element1", element1) .AddNullElement("element2", element2) .AddDataAssociation("assoc", DataAssociation.Create("element1", "a", "element2", "a")); var models = new InMemoryProcessModelsStore(); models.Store(model); var manager = new ProcessManager( models, new InMemoryProcessInstancesStore() ); var instance = ProcessInstance.Create(model); manager.Attach(instance); var context = new ExecutionContext(manager, model, instance, instance.Token, null); output.Update(context, "element1", "Hello World"); input.GetCurrentValue(context, "element2").Should().Be("Hello World"); }
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 AddingEventCatcherOnlyWithTypeCreatesAnElementWithLogicalName() { var model = ProcessModel.Create() .AddEventCatcherFor <ProductOrdered>(); model.GetElementByName("OnProductOrdered").Should().NotBeNull(); }
public void ReturnTwoTokensWhenStartEventHaveTwoOutcomingConnections() { var model = ProcessModel.Create() .AddEventCatcher( "start", CatchAnyEventCatcher.Create() ) .AddEventCatcher( "middle1", CatchAnyEventCatcher.Create() ) .AddEventCatcher( "middle2", CatchAnyEventCatcher.Create() ) .AddEventThrower( "end", SilentEventThrower.Instance ) .AddSequenceFlow("start", "middle1") .AddSequenceFlow("start", "middle2") .AddSequenceFlow("middle1", "end") .AddSequenceFlow("middle2", "end"); var instance = ProcessInstance.Create(model.Id); var context = new ExecutionContext(null, model, instance, instance.Token, null); var tokens = instance.HandleEvent(context, new object()); tokens.Count().Should().Be(2); tokens.Select(token => token.ExecutionPoint) .Should().BeEquivalentTo("middle1", "middle2"); }
public void AddingActivityOnlyWithTypeCreatesAnElementWithLogicalName() { var model = ProcessModel.Create() .AddActivity <CheckStockActivity>(); model.GetElementByName("CheckStock").Should().NotBeNull(); }
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 SaveStartEventNameAtTheFirstHistoryEntry() { var model = ProcessModel.Create() .AddEventCatcher( "start", CatchAnyEventCatcher.Create() ) .AddEventCatcher( "middle", CatchAnyEventCatcher.Create() ) .AddEventThrower( "end", SilentEventThrower.Instance ) .AddSequenceFlow("start", "middle") .AddSequenceFlow("middle", "end"); var instance = ProcessInstance.Create(Guid.Parse(model.Id)); var context = new ExecutionContext(null, model, instance, instance.Token, null); instance.HandleEvent( context, new object() ); instance.History.First().ExecutionPoint.Should().Be("start"); }
public void BeRunningAfterHandlingValidStartEvent() { var model = ProcessModel.Create() .AddEventCatcher( "start", CatchAnyEventCatcher.Create() ) .AddEventCatcher( "middle", CatchAnyEventCatcher.Create() ) .AddEventThrower( "end", SilentEventThrower.Instance ) .AddSequenceFlow("start", "middle", "end"); var instance = ProcessInstance.Create(Guid.Parse(model.Id)); var context = new ExecutionContext(null, model, instance, instance.Token, null); instance.HandleEvent( context, new object() ); instance.IsRunning.Should().BeTrue(); instance.Token.ExecutionPoint.Should().Be("middle"); }
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 FinishWhenMeetingTheEnd() { var model = ProcessModel.Create() .AddEventCatcher( "start", CatchAnyEventCatcher.Create() ) .AddEventCatcher( "middle", CatchAnyEventCatcher.Create() ) .AddEventThrower( "end", SilentEventThrower.Instance ) .AddSequenceFlow("start", "middle") .AddSequenceFlow("middle", "end"); var instance = ProcessInstance.Create(model.Id); var context = new ExecutionContext(null, model, instance, instance.Token, null); // start instance.HandleEvent( context, new object() ).Should().BeEquivalentTo(instance.Token); // middle instance.HandleEvent( context, new object() ).Should().BeEmpty(); instance.IsRunning.Should().BeFalse(); instance.IsDone.Should().BeTrue(); }
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 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 AddEventCatcherShouldCreateDefaultHandlerWhenItIsNotSpecified() { var model = ProcessModel.Create() .AddEventCatcher("start"); var element = model.GetElementByName("start")?.Element; element.Should().BeOfType <CatchAnyEventCatcher>(); }
public void AddEventThrowerShouldCreateDefaultThrowerWhenItIsNotSpecified() { var model = ProcessModel.Create() .AddEventThrower("end"); var element = model.GetElementByName("end")?.Element; element.Should().BeOfType <SilentEventThrower>(); }
public void AnswerIfCouldStartWithSpecificEvent() { var model = ProcessModel.Create() .AddEventCatcher("start", TypedEventCatcher <Start> .Create()) .AddEventThrower("end", SilentEventThrower.Instance) .AddSequenceFlow("start", "end"); model.CanStartWith(new ExecutionContext(null, null, null, null, null), new object()).Should().BeFalse(); model.CanStartWith(new ExecutionContext(null, null, null, null, null), new Start()).Should().BeTrue(); }
public void ThrowArgumentWhenInsertingElementWithDuplicatedName() { Action act = () => { var processModel = ProcessModel.Create() .AddActivity("act1", LambdaActivity.Create(() => { })) .AddActivity("act1", LambdaActivity.Create(() => { })); }; act.Should().Throw <ArgumentException>(); }
public void AcceptModelsWhenAllActivitiesHaveOutcomingConnections() { var model = ProcessModel.Create() .AddAnyEventCatcher("start") .AddActivity("none", () => { }) .AddEventThrower("end") .AddSequenceFlow("start", "none", "end"); new EnsureThereAreOutcomingConnectionsWhenNecessaryValidationRule() .Validate(model).Should().BeEmpty(); }
public void StoreFlow() { var model = ProcessModel.Create(Guid.Parse("459f7fad-9ab9-45d5-aff9-f420d89477db")) .AddEventCatcherFor <InboundOrderAvailableToUnload>("start") .AddActivity <CreatePalletsToUnload>() .AddActivityWithCompensation <CreateCheckTasksForUnloadedPallets, CancelCheckTasksForPallets>() .AddEventThrower <CheckTasksCreated>() .AddSequenceFlow("start", nameof(CreatePalletsToUnload), nameof(CreateCheckTasksForUnloadedPallets), "end"); ProcessManagerHolder.Instance.ModelsStore.Store(model); }
public void RejectModelsWhenOneEventCatcherHasNoOutcomingConnections(string catcherName) { var model = ProcessModel.Create() .AddAnyEventCatcher(catcherName) .AddEventThrower("end") .AddSequenceFlow("start", "end"); var result = new EnsureThereAreOutcomingConnectionsWhenNecessaryValidationRule() .Validate(model).ToArray(); result.Should().NotBeEmpty(); result.First().Message.Should().Be($"'{catcherName}' has no outgoing connections."); }
public void TokenShouldNotBeActiveWhenProcessIsDone() { var model = ProcessModel.Create() .AddEventCatcher("start", CatchAnyEventCatcher.Create()) .AddEventThrower("end", SilentEventThrower.Instance) .AddSequenceFlow("start", "end"); var instance = ProcessInstance.Create(model.Id); var context = new ExecutionContext(null, model, instance, instance.Token, null); instance.HandleEvent(context, new object()); instance.Token.WasReleased.Should().BeTrue(); instance.Token.IsActive.Should().BeFalse(); }
public void BasicSetup() { var passed = false; var model = ProcessModel.Create() .AddEventCatcher("start", CatchAnyEventCatcher.Create()) .AddActivity("activity", LambdaActivity.Create(() => passed = true)) .AddEventThrower("end", SilentEventThrower.Instance) .AddSequenceFlow("start", "activity", "end"); var instance = ProcessInstance.Create(model.Id); var context = new ExecutionContext(null, model, instance, instance.Token, null); instance.HandleEvent(context, new object()); passed.Should().BeTrue(); }
public void EnumerateStartEventCatchers() { var processModel = ProcessModel.Create() .AddEventCatcher( "start", CatchAnyEventCatcher.Create() ) .AddEventThrower( "end", SilentEventThrower.Instance ) .AddSequenceFlow("start", "end"); var catchers = processModel.GetStartEventCatchers(); Assert.Single(catchers); }
public void SaveEventDataAsDataObject(object data) { var model = ProcessModel.Create() .AddAnyEventCatcher("OnMessageReceived") .AddEventThrower("GoodBye", SilentEventThrower.Instance) .AddSequenceFlow("OnMessageReceived", "GoodBye"); var manager = new ProcessManager( new InMemoryProcessModelsStore(model), new InMemoryProcessInstancesStore() ); var result = manager.HandleEvent(data); var pinstance = manager.InstancesStore.GetById(result.First().ProcessInstanceId); pinstance.GetDataObjectValue("MessageReceived").Should().Be(data); }
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 ThrowArgumentExceptionWhenTryingToAttachInstanceWithUnrecognizedModel() { var model = ProcessModel.Create() .AddAnyEventCatcher("start") .AddEventThrower("end"); var manager = new ProcessManager( new InMemoryProcessModelsStore(), new InMemoryProcessInstancesStore() ); var instance = ProcessInstance.Create(model); Action sut = () => manager.Attach(instance); sut.Should().Throw <ArgumentException>(); }
public static ProcessModel CreateModel() { return(ProcessModel.Create() .AddEventCatcherFor <ProductOrdered>() .AddActivity <CheckStockActivity>() .AddExclusiveGateway("InStock?") .AddSequenceFlow("OnProductOrdered", "CheckStock", "InStock?") .AddActivity <PickStockActivity>() .AddActivity <ShipOrderActivity>() .AddEventThrower <InStockEventThrower>() .AddSequenceFlow("PickStock", "ShipOrder", "InStock") .AddConditionalSequenceFlow("InStock?", "PickStock", true) .AddEventThrower <OutOfStockEventThrower>() .AddConditionalSequenceFlow("InStock?", "OutOfStock", false)); }
public void ReturnElementByName() { var obj = NamedProcessElement <IEventThrower> .Create("middle", SilentEventThrower.Instance); var processModel = ProcessModel.Create() .AddEventCatcher( "start", CatchAnyEventCatcher.Create() ) .AddEventThrower(obj) .AddEventThrower( "end", SilentEventThrower.Instance ) .AddSequenceFlow("start", "middle") .AddSequenceFlow("middle", "end"); processModel.GetElementByName("middle").Should().Be(obj); }
public void RefuseEventsWhenItIsDone() { var count = 0; var model = ProcessModel.Create() .AddEventCatcher("start", CatchAnyEventCatcher.Create()) .AddActivity("a1", LambdaActivity.Create(() => count++)) .AddActivity("a2", LambdaActivity.Create(() => count++)) .AddActivity("a3", LambdaActivity.Create(() => count++)) .AddEventThrower("end", SilentEventThrower.Instance) .AddSequenceFlow("start", "a1", "a2", "a3", "end"); var instance = ProcessInstance.Create(model.Id); var context = new ExecutionContext(null, model, instance, instance.Token, null); instance.HandleEvent(context, new object()); instance.HandleEvent(context, new object()); count.Should().Be(3); }
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); }