public void All_sync_handlers_performs_one_after_one()
        {
            Sys.InitLocalTransportExtension();
            var delayActor = Sys.ActorOf(Props.Create(() => new EchoSleepActor(TimeSpan.FromMilliseconds(50), TestActor)));
            var catalog    = new HandlersDefaultProcessor();

            catalog.Add <BalloonCreated>(new SyncProjectionProcessor(delayActor));
            catalog.Add <BalloonTitleChanged>(new SyncProjectionProcessor(delayActor));
            catalog.Add <BalloonTitleChanged>(new SyncProjectionProcessor(delayActor));

            var actor = Sys.ActorOf(Props.Create(() => new HandlersPipeActor(catalog, TestActor)));

            actor.Tell(MessageMetadataEnvelop.New(new BalloonCreated("1", Guid.NewGuid().ToString())));

            //in sync process we should wait for handlers execution
            //in same order as they were sent to handlers process actor
            ExpectMsg <MarkedHandlerExecutedMessage>();
            ExpectMsg <IMessageMetadataEnvelop <DomainEvent> >();
            //HandlersProcessActor should notify sender (TestActor) of initial messages that work is done
            ExpectMsg <AllHandlersCompleted>();

            actor.Tell(MessageMetadataEnvelop.New(new BalloonTitleChanged("2", Guid.NewGuid().ToString())));
            ExpectMsg <MarkedHandlerExecutedMessage>();
            ExpectMsg <MarkedHandlerExecutedMessage>();
            //HandlersProcessActor should notify next step - process actor that work is done
            ExpectMsg <IMessageMetadataEnvelop <DomainEvent> >();
            ExpectMsg <AllHandlersCompleted>();
        }
        public void Condition_wait_end_should_be_true_on_B_and_C()
        {
            var sampleObjectsReceived = new object[]
            {
                MessageMetadataEnvelop.New(_messageB),
                MessageMetadataEnvelop.New(_messageC)
            };

            Assert.True(Waiter.ConditionBuilder.StopCondition(sampleObjectsReceived));
        }
예제 #3
0
        public void Process_transition_raises_state_events()
        {
            _processActor.Ref.Tell(MessageMetadataEnvelop.New(new BalloonCreated("1", Guid.NewGuid().ToString(), DateTime.Now, _processId),
                                                              MessageMetadata.Empty));

            _localAkkaEventBusTransport.Subscribe(typeof(IMessageMetadataEnvelop), TestActor);

            FishForMessage <MessageMetadataEnvelop>(m => m.Message is ProcessManagerCreated <TestState>);
            FishForMessage <MessageMetadataEnvelop>(m => m.Message is ProcessReceivedMessage <TestState>);
        }
예제 #4
0
        public void Process_change_state_after_transitions()
        {
            var domainEventA = new BalloonCreated("1", Guid.NewGuid().ToString(), DateTime.Now, _processId);

            _processActor.Ref.Tell(MessageMetadataEnvelop.New(domainEventA));

            var msg = ExpectMsg <ProcessTransited>();

            Assert.Equal(domainEventA.SourceId, ((TestState)msg.NewProcessState).ProcessingId);
        }
        public void Given_no_processors_pipe_still_reply_with_completed_messages()
        {
            var catalog = new HandlersDefaultProcessor();

            Sys.InitLocalTransportExtension();
            var actor = Sys.ActorOf(Props.Create(() => new HandlersPipeActor(catalog, TestActor)));

            var sampleAggregateCreatedEvent = new BalloonCreated("1", Guid.NewGuid().ToString());

            actor.Tell(MessageMetadataEnvelop.New(sampleAggregateCreatedEvent, MessageMetadata.Empty));

            //HandlersPipeActor should notify next step - process actor that work is done
            ExpectMsg <IMessageMetadataEnvelop <DomainEvent> >();
            //HandlersPipeActor should notify sender (TestActor) of initial messages that work is done
            ExpectMsg <AllHandlersCompleted>();
        }
        public async Task ProcessManagerPipeActor_does_not_support_domain_event_inheritance()
        {
            var testProcessActor = Sys.ActorOf(Props.Create(() => new TestProcessActor(TestActor, Guid.NewGuid().ToString(), null)));
            var catalog          = new ProcessesDefaultProcessor();

            catalog.Add <BalloonCreated>(new SyncProcessManagerProcessor(testProcessActor));

            var processPipeActor = Sys.ActorOf(Props.Create(() => new ProcessesPipeActor(catalog)));
            await processPipeActor.Ask <Initialized>(new Initialize(TestActor));

            var msg = MessageMetadataEnvelop.New <DomainEvent>(new Inherited());

            processPipeActor.Tell(msg);
            ExpectMsg <ProcessesTransitComplete>();
            //process processor did not run due to error, but we received processing complete message
            ExpectNoMsg(TimeSpan.FromSeconds(1));
        }
예제 #7
0
        public void Process_actor_process_one_message_in_time()
        {
            var domainEventA = new BalloonCreated("1", Guid.NewGuid().ToString(), DateTime.Now, _processId);
            var domainEventB = new BalloonTitleChanged("2", Guid.NewGuid().ToString(), DateTime.Now, _processId);

            _processActor.Tell(MessageMetadataEnvelop.New(domainEventA, MessageMetadata.Empty));
            _processActor.Tell(MessageMetadataEnvelop.New(domainEventB, MessageMetadata.Empty));

            //A was received first and should be processed first
            var msg = ExpectMsg <ProcessTransited>();

            Assert.Equal(domainEventA.SourceId, ((TestState)msg.NewProcessState).ProcessingId);
            //B should not be processed after A is completed
            var msgB = ExpectMsg <ProcessTransited>();

            Assert.Equal(domainEventB.SourceId, ((TestState)msgB.NewProcessState).ProcessingId);
        }
        public void CustomHandlerExecutor_does_not_support_domain_event_inheritance()
        {
            Sys.InitLocalTransportExtension();

            var catalog = new HandlersDefaultProcessor();

            catalog.Add <BalloonCreated>(new SyncProjectionProcessor(TestActor));
            var actor = Sys.ActorOf(Props.Create(() => new HandlersPipeActor(catalog, TestActor)));

            var msg = MessageMetadataEnvelop.New(new Inherited());

            actor.Tell(msg);
            //processor did not run, but we pass message to process after
            ExpectMsg <MessageMetadataEnvelop <Inherited> >();
            //processor did not run, but we received processing complete message
            ExpectMsg <AllHandlersCompleted>();
        }
        public void CustomHandlerProcessor_routes_events_by_type()
        {
            Sys.InitLocalTransportExtension();

            var catalog = new HandlersDefaultProcessor();

            catalog.Add <BalloonCreated>(new FireAndForgetActorMessageProcessor(TestActor));
            var actor = Sys.ActorOf(Props.Create(() => new HandlersPipeActor(catalog, TestActor)));

            actor.Tell(MessageMetadataEnvelop.New(new BalloonCreated("1", Guid.NewGuid().ToString())));

            //TestActor as processor receives message for work
            ExpectMsg <MessageMetadataEnvelop <BalloonCreated> >();
            //HandlersProcessActor should resend domain event to next step - process actor - for processing
            ExpectMsg <MessageMetadataEnvelop <BalloonCreated> >();
            //HandlersProcessActor should notify sender (TestActor) of initial messages that work is done
            ExpectMsg <AllHandlersCompleted>();
        }
        public void Sync_and_async_handlers_performs_independent()
        {
            Sys.InitLocalTransportExtension();

            var fastHandler = Sys.ActorOf(Props.Create(() => new EchoSleepActor(TimeSpan.FromMilliseconds(1), TestActor)));
            var slowHandler = Sys.ActorOf(Props.Create(() => new EchoSleepActor(TimeSpan.FromMilliseconds(500), TestActor)));
            var catalog     = new HandlersDefaultProcessor();

            //Slow handler will receive messages first.
            //Due to it is registered with async process policy
            //second handler (fast) will not wait for slow one and it will finish execution before slow handler
            catalog.Add <BalloonCreated>(new FireAndForgetActorMessageProcessor(slowHandler));
            catalog.Add <BalloonCreated>(new SyncProjectionProcessor(fastHandler));

            catalog.Add <BalloonTitleChanged>(new FireAndForgetActorMessageProcessor(slowHandler));
            catalog.Add <BalloonTitleChanged>(new SyncProjectionProcessor(fastHandler));

            var actor = Sys.ActorOf(Props.Create(() => new HandlersPipeActor(catalog, TestActor)));

            actor.Tell(MessageMetadataEnvelop.New(new BalloonCreated("1", Guid.NewGuid().ToString())));
            actor.Tell(MessageMetadataEnvelop.New(new BalloonTitleChanged("1", Guid.NewGuid().ToString())));

            ExpectMsg <MarkedHandlerExecutedMessage>((e, s) => e.ProcessingMessage.Message is BalloonCreated && s == fastHandler);
            ExpectMsg <IMessageMetadataEnvelop <BalloonCreated> >();
            ExpectMsg <AllHandlersCompleted>(); //for balloon created


            ExpectMsg <MarkedHandlerExecutedMessage>((e, s) => e.ProcessingMessage.Message is BalloonTitleChanged && s == fastHandler);
            //HandlersProcessActor should notify next step - process actor that work is done
            ExpectMsg <IMessageMetadataEnvelop <BalloonTitleChanged> >();

            //HandlersProcessActor should notify sender (TestActor) of initial messages that work is done
            ExpectMsg <AllHandlersCompleted>();

            //slow fire and  handlers will finish execution in undetermined order
            ExpectMsg <MarkedHandlerExecutedMessage>();
            ExpectMsg <MarkedHandlerExecutedMessage>();
        }
        public async Task All_Processes_performs_linear_and_results_from_all_processes_are_gathered()
        {
            var processAId = Guid.NewGuid().ToString();

            _output.WriteLine("Process A:" + processAId);
            var testProcessActorA =
                Sys.ActorOf(Props.Create(() => new TestProcessActor(TestActor, processAId, TimeSpan.FromMilliseconds(1000))));

            var processBId = Guid.NewGuid().ToString();

            _output.WriteLine("Process B:" + processBId);

            var testProcessActorB =
                Sys.ActorOf(Props.Create(() => new TestProcessActor(TestActor,
                                                                    processBId,
                                                                    TimeSpan.FromMilliseconds(50))));
            var processCId = Guid.NewGuid().ToString();

            _output.WriteLine("Process C:" + processCId);

            var testProcessActorC =
                Sys.ActorOf(Props.Create(() => new TestProcessActor(TestActor, processCId, TimeSpan.FromMilliseconds(50))));

            var catalog = new ProcessesDefaultProcessor();

            catalog.Add <BalloonCreated>(new SyncProcessManagerProcessor(testProcessActorA));
            catalog.Add <BalloonTitleChanged>(new SyncProcessManagerProcessor(testProcessActorB));
            catalog.Add <BalloonTitleChanged>(new SyncProcessManagerProcessor(testProcessActorC));


            var balloonCreated      = new BalloonCreated("1", Guid.NewGuid().ToString());
            var balloonTitleChanged = new BalloonTitleChanged("2", Guid.NewGuid().ToString());


            //var resultA = await catalog.Process(MessageMetadataEnvelop.New<DomainEvent>(balloonCreated));
            //var resultB = await catalog.Process(MessageMetadataEnvelop.New<DomainEvent>(balloonTitleChanged));



            var processPipeActor = Sys.ActorOf(Props.Create(() => new ProcessesPipeActor(catalog)));
            await processPipeActor.Ask <Initialized>(new Initialize(TestActor));

            processPipeActor.Tell(MessageMetadataEnvelop.New <DomainEvent>(balloonCreated));
            processPipeActor.Tell(MessageMetadataEnvelop.New <DomainEvent>(balloonTitleChanged));

            //process pipe will process domain event linear on each message
            //but for don't wait for each message execution end, so first will complete process of second message - balloonTitleChanged

            //after process pipe will proceed with balloonTitleChanged event, pass it linear to two left process managers

            var transited   = ExpectMsg <ProcessTransited>(TimeSpan.FromSeconds(600));
            var testCommand = transited.ProducedCommands.OfType <TestCommand>().First();

            Assert.Equal(processBId, testCommand.ProcessId);


            transited   = ExpectMsg <ProcessTransited>();
            testCommand = transited.ProducedCommands.OfType <TestCommand>().First();
            Assert.Equal(processCId, testCommand.ProcessId);

            //after it process pipe is finished with ballon created message processing, gathering results
            //and sending it to commandPipe (testActor)
            var cmdB = ExpectMsg <MessageMetadataEnvelop <ICommand> >();

            Assert.Equal(processBId, cmdB.Message.ProcessId);

            var cmdC = ExpectMsg <MessageMetadataEnvelop <ICommand> >();

            Assert.Equal(processCId, cmdC.Message.ProcessId);

            //than it will report end of domain event processing
            ExpectMsg <ProcessesTransitComplete>();

            //than slow processing of first message will finish

            //test process actors sends to us messages on complete
            //wait for test process actor transit on first event

            transited   = ExpectMsg <ProcessTransited>();
            testCommand = transited.ProducedCommands.OfType <TestCommand>().First();
            Assert.Equal(processAId, testCommand.ProcessId);

            var cmdA = ExpectMsg <MessageMetadataEnvelop <ICommand> >();

            Assert.Equal(processAId, cmdA.Message.ProcessId);
            //process pipe has only one handler for balloonCreated, so it will finish processing
            //and send us a message
            ExpectMsg <ProcessesTransitComplete>();
        }