Example #1
0
        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();
        }
Example #2
0
        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);
        }
Example #4
0
        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");
        }
Example #6
0
        public void AddingActivityOnlyWithTypeCreatesAnElementWithLogicalName()
        {
            var model = ProcessModel.Create()
                        .AddActivity <CheckStockActivity>();

            model.GetElementByName("CheckStock").Should().NotBeNull();
        }
Example #7
0
        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);
        }
Example #11
0
        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();
        }
Example #12
0
        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);
        }
Example #13
0
    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);
    }
Example #14
0
        public void AddEventCatcherShouldCreateDefaultHandlerWhenItIsNotSpecified()
        {
            var model = ProcessModel.Create()
                        .AddEventCatcher("start");

            var element = model.GetElementByName("start")?.Element;

            element.Should().BeOfType <CatchAnyEventCatcher>();
        }
Example #15
0
        public void AddEventThrowerShouldCreateDefaultThrowerWhenItIsNotSpecified()
        {
            var model = ProcessModel.Create()
                        .AddEventThrower("end");

            var element = model.GetElementByName("end")?.Element;

            element.Should().BeOfType <SilentEventThrower>();
        }
Example #16
0
        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();
        }
Example #17
0
        public void ThrowArgumentWhenInsertingElementWithDuplicatedName()
        {
            Action act = () =>
            {
                var processModel = ProcessModel.Create()
                                   .AddActivity("act1", LambdaActivity.Create(() => { }))
                                   .AddActivity("act1", LambdaActivity.Create(() => { }));
            };

            act.Should().Throw <ArgumentException>();
        }
Example #18
0
        public void AcceptModelsWhenAllActivitiesHaveOutcomingConnections()
        {
            var model = ProcessModel.Create()
                        .AddAnyEventCatcher("start")
                        .AddActivity("none", () => { })
                        .AddEventThrower("end")
                        .AddSequenceFlow("start", "none", "end");

            new EnsureThereAreOutcomingConnectionsWhenNecessaryValidationRule()
            .Validate(model).Should().BeEmpty();
        }
Example #19
0
        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);
        }
Example #20
0
        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.");
        }
Example #21
0
        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();
        }
Example #22
0
        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();
        }
Example #23
0
        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);
        }
Example #24
0
        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);
        }
Example #25
0
        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);
        }
Example #26
0
        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>();
        }
Example #27
0
        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));
        }
Example #28
0
        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);
        }
Example #29
0
        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);
        }
Example #30
0
        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);
        }