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

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

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

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

            actor.Tell(new MessageMetadataEnvelop(sampleAggregateCreatedEvent));

            //HandlersProcessActor should notify next step - process actor that work is done
            ExpectMsg <IMessageMetadataEnvelop>(m => m.Message is DomainEvent);
            ExpectMsg <AllHandlersCompleted>();
            //but handlers will finish their work later in undefined sequence

            actor.Tell(new MessageMetadataEnvelop(sampleAggregateChangedEvent));
            ExpectMsg <IMessageMetadataEnvelop>(m => m.Message is DomainEvent);
            //HandlersProcessActor should notify sender (TestActor) of initial messages that work is done
            ExpectMsg <AllHandlersCompleted>();
        }
示例#2
0
 public static BalloonCatalogItem ToCatalogItem(this BalloonCreated e)
 {
     return(new BalloonCatalogItem()
     {
         BalloonId = e.SourceId,
         LastChanged = e.CreatedTime,
         Title = e.Value
     });
 }
示例#3
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 async Task Handle(BalloonCreated msg, IMessageMetadata metadata = null)
        {
            _log.Debug("Projecting balloon catalog from message {@msg}", msg);
            using (var context = _contextCreator())
            {
                context.BalloonCatalog.Add(msg.ToCatalogItem());
                await context.SaveChangesAsync();

                _publisher.Publish(new BalloonCreatedNotification()
                {
                    BallonId = msg.SourceId
                },
                                   metadata.CreateChild(Guid.NewGuid().ToString(), _readModelUpdatedProcessEntry));
            }
        }
        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>();
        }
示例#6
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 async Task Given_only_aggregate_events_persisted_it_can_be_loaded(IRepository <DomainEvent> eventRepo,
                                                                                 AggregateRepository aggrRepo)
        {
            try
            {
                _sourceId = Guid.NewGuid().ToString();
                _created  = new BalloonCreated("initial value", _sourceId);
                _changed  = new BalloonTitleChanged("changed value", _sourceId);

                var persistenceId = EntityActorName.New <Balloon>(_sourceId).ToString();
                await eventRepo.Save(persistenceId, _created, _changed);

                _aggregate = await aggrRepo.LoadAggregate <Balloon>(_sourceId);

                Assert.Equal(_sourceId, _aggregate.Id);
                Assert.Equal(_changed.Value, _aggregate.Title);
            }
            finally
            {
                eventRepo.Dispose();
                aggrRepo.Dispose();
            }
        }
        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>();
        }
 //can change to Apply<T> call in constructor, left for testing
 public void Apply(BalloonCreated e)
 {
     Id = e.Id;
     Title = e.Value;
 }