예제 #1
0
 public IExpectBuilder <T> Or(Type type, Func <object, bool> filter)
 {
     WaitIsOver = WaitIsOver.Or(c => c != null && c.Any(filter));
     Waiter.Subscribe(type, filter, WaitIsOver.Compile());
     Waiter.Subscribe(MessageMetadataEnvelop.GenericForType(type), filter, WaitIsOver.Compile());
     return(this);
 }
        public async Task Execute(ICommand command, IMessageMetadata metadata = null, CommandConfirmationMode confirmationMode = CommandConfirmationMode.Projected)
        {
            var envelopedCommand = new MessageMetadataEnvelop(command, metadata ?? CreateEmptyCommandMetadata(command));

            if (confirmationMode == CommandConfirmationMode.None)
            {
                _commandExecutorActor.Tell(envelopedCommand);
                return;
            }

            var inbox = Inbox.Create(_system);

            _commandExecutorActor.Tell(envelopedCommand, inbox.Receiver);

            var msg = await inbox.ReceiveAsync(_defaultTimeout);

            if (CheckMessage(confirmationMode, msg))
            {
                return;
            }

            msg = await inbox.ReceiveAsync(_defaultTimeout);

            if (CheckMessage(confirmationMode, msg))
            {
                return;
            }

            throw new TimeoutException("Command execution took to long");
        }
        public void Publish(object msg, IMessageMetadata metadata)
        {
            _local.Publish(msg);
            var messageMetadataEnvelop = MessageMetadataEnvelop.NewGeneric(msg, metadata);

            _remoteSubscriber.Ask <PublishAck>(new Publish(messageMetadataEnvelop), _timeout).Wait();
        }
        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 AggregatePersistedHub_Infrastructure(ActorSystem system)
 {
     ChildId              = Guid.NewGuid();
     ChildCreateMessage   = new MessageMetadataEnvelop <ICommand>(new CreateSampleAggregateCommand(42, ChildId), new MessageMetadata(ChildId));
     ChildActivateMessage = new MessageMetadataEnvelop <ICommand>(new ChangeSampleAggregateCommand(100, ChildId), new MessageMetadata(ChildId));
     HubProps             = system.DI().Props <AggregateHubActor <SampleAggregate> >();
 }
 public AggregatePersistedHubInfrastructure()
 {
     ChildId            = Guid.NewGuid().ToString();
     ChildCreateMessage = new MessageMetadataEnvelop <ICommand>(new InflateNewBallonCommand(42, ChildId),
                                                                MessageMetadata.New(ChildId, null, null));
     ChildActivateMessage = new MessageMetadataEnvelop <ICommand>(new WriteTitleCommand(100, ChildId),
                                                                  MessageMetadata.New(ChildId, null, null));
 }
예제 #7
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 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));
        }
예제 #9
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>);
        }
예제 #10
0
        public static CreateActorRouteMessage ForAggregate(string name, IAggregateCommandsHandlerDesriptor descriptor)
        {
            var messageRoutes = descriptor.RegisteredCommands.Select(c => new MessageRoute
                                                                     (
                                                                         MessageMetadataEnvelop.GenericForType(c.CommandType),
                                                                         c.Property
                                                                     )).ToArray();

            var hubType = typeof(AggregateHubActor <>).MakeGenericType(descriptor.AggregateType);

            return(new CreateActorRouteMessage(hubType, name, PoolKind.None, messageRoutes));
        }
            public ProcessHubInfrastructure()
            {
                var processId = Guid.NewGuid().ToString();

                ChildId = processId;
                var gotTired       = new GotTiredEvent(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), processId);
                var coffeMadeEvent = new CoffeMadeEvent(gotTired.FavoriteCoffeMachineId, gotTired.PersonId, null, processId);

                ChildCreateMessage = new MessageMetadataEnvelop <DomainEvent>(gotTired, MessageMetadata.New(gotTired.SourceId, null, null));
                //TODO: second message will not hit same process as created by previos,
                //think how to change it.
                ChildActivateMessage = new MessageMetadataEnvelop <DomainEvent>(coffeMadeEvent,
                                                                                MessageMetadata.New(coffeMadeEvent.SourceId, null, null));
            }
예제 #12
0
        public void Message_Envelop_should_be_serializable()
        {
            var evt   = new BalloonTitleChanged("123", Guid.NewGuid().ToString());
            var fault = new Fault <BalloonTitleChanged>(evt, new Exception(), typeof(object), Guid.NewGuid().ToString(), DateTime.Now);
            //Fault
            //ballonTitleChanged
            var msg        = new MessageMetadataEnvelop <Fault <BalloonTitleChanged> >(fault, MessageMetadata.Empty);
            var serializer = new DebugHyperionSerializer((ExtendedActorSystem)TestActorSystem.Create());

            var bytes    = serializer.ToBinary(msg);
            var restored = serializer.FromBinary(bytes, typeof(MessageMetadataEnvelop <Fault <BalloonTitleChanged> >));

            Assert.NotNull(restored);
        }
        public void CommandExecutor_does_not_support_command_inheritance()
        {
            var catalog = new TypeCatalog <IActorRef, object>();

            catalog.Add <InflateNewBallonCommand>(TestActor);

            var actor = Sys.ActorOf(Props.Create(() => new AggregatesPipeActor(catalog)));

            var msg = new MessageMetadataEnvelop <CreateCommand>(new CreateCommand(1, Guid.NewGuid().ToString()), MessageMetadata.Empty);

            actor.Tell(msg);

            ExpectNoMsg();
        }
예제 #14
0
        public static CreateActorRouteMessage ForSaga(ISagaDescriptor descriptor, string name = null)
        {
            name = name ?? $"SagaHub_{descriptor.SagaType.BeautyName()}";

            var messageRoutes = descriptor.AcceptMessages
                                .Select(messageBinder => new MessageRoute(
                                            MessageMetadataEnvelop.GenericForType(messageBinder.MessageType),
                                            messageBinder.CorrelationField))
                                .ToArray();

            var hubType = typeof(SagaHubActor <,>).MakeGenericType(descriptor.SagaType,
                                                                   descriptor.StateType);

            return(new CreateActorRouteMessage(hubType, name, PoolKind.None, messageRoutes));
        }
        public void CommandExecutor_routes_command_by_its_type()
        {
            var catalog = new TypeCatalog <IActorRef, object>();

            catalog.Add <InflateNewBallonCommand>(TestActor);

            var actor = Sys.ActorOf(Props.Create(() => new AggregatesPipeActor(catalog)));

            var msg = new MessageMetadataEnvelop <ICommand>(new InflateNewBallonCommand(1, Guid.NewGuid().ToString()),
                                                            MessageMetadata.Empty);

            actor.Tell(msg);

            ExpectMsg <MessageMetadataEnvelop <ICommand> >();
        }
        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 StateSagaPersistedHub_Infrastructure(ActorSystem system)
        {
            var sagaId = Guid.NewGuid();

            ChildId = sagaId;
            var gotTired       = new GotTiredEvent(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), sagaId);
            var coffeMadeEvent = new CoffeMadeEvent(gotTired.FavoriteCoffeMachineId, gotTired.PersonId, null, sagaId);

            ChildCreateMessage = new MessageMetadataEnvelop <DomainEvent>(gotTired,
                                                                          new MessageMetadata(gotTired.SourceId));

            ChildActivateMessage = new MessageMetadataEnvelop <DomainEvent>(coffeMadeEvent,
                                                                            new MessageMetadata(coffeMadeEvent.SourceId));

            HubProps = system.DI().Props <SagaHubActor <SoftwareProgrammingSaga, SoftwareProgrammingSagaState> >();
        }
예제 #18
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);
        }
예제 #19
0
        public async Task <IWaitResults> Execute(params ICommand[] commands)
        {
            foreach (var command in commands)
            {
                _waiter.ExpectBuilder.Or(MessageMetadataEnvelop.GenericForType(Fault.TypeFor(command)),
                                         f => (((f as IMessageMetadataEnvelop)?.Message as IFault)?.Message as ICommand)?.Id == command.Id);
            }

            var task = _waiter.Start();

            foreach (var command in commands)
            {
                Executor.Execute(command);
            }

            var res = await task;

            if (!_failOnFaults)
            {
                return(res);
            }

            var faults = new List <IFault>();

            foreach (var m in res.All)
            {
                var fault = m as IFault;
                if (fault != null)
                {
                    faults.Add(fault);
                }

                var envelopedFault = m as IMessageMetadataEnvelop <IFault>;
                if (envelopedFault != null)
                {
                    faults.Add(envelopedFault.Message);
                }
            }

            if (faults.Any())
            {
                throw new AggregateException(faults.Select(f => f.Exception));
            }

            return(res);
        }
        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 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));
        }
        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>();
        }
예제 #23
0
        private void CreatingProcessBehavior()
        {
            Receive <CreateNewProcess>(c =>
            {
                _log.Debug("Creating new process instance from {@message}", c);
                var pendingState = _processStateFactory.Create(c.Message.Message);

                ExecutionContext.StartNewExecution(pendingState, c.Message, Sender);

                var cmd = new CreateNewStateCommand <TState>(ExecutionContext.PendingState.Id, ExecutionContext.PendingState);
                //will reply with CommandExecuted
                _stateAggregateActor.Tell(new MessageMetadataEnvelop <ICommand>(cmd, ExecutionContext.ProcessingMessage.Metadata));
                Behavior.Become(AwaitingCreationConfirmationBehavior, nameof(AwaitingCreationConfirmationBehavior));
            });

            void AwaitingCreationConfirmationBehavior()
            {
                Receive <Status.Failure>(f => FinishWithError(ExecutionContext.ProcessingMessage, ExecutionContext.ProcessingMessageSender, f.Cause));

                //from state aggregate actor after persist
                Receive <AggregateActor.CommandExecuted>(c =>
                {
                    _log.Debug("Process instance created by message {@processResult}", ExecutionContext.ProcessingMessage);

                    var pendingStateId = ExecutionContext.PendingState.Id;
                    if (Id != pendingStateId)
                    {
                        _log.Debug("Redirecting message to newly created process state instance, {id}", pendingStateId);
                        var redirect = new MessageMetadataEnvelop(new ProcessRedirect(pendingStateId, ExecutionContext.ProcessingMessage), ExecutionContext.ProcessingMessage.Metadata);
                        //requesting redirect from parent - persistence hub
                        Context.Parent.Tell(redirect, ExecutionContext.ProcessingMessageSender);
                        Behavior.Become(AwaitingMessageBehavior, nameof(AwaitingMessageBehavior));
                        ExecutionContext.Clear();
                        return;
                    }

                    State = ExecutionContext.PendingState;
                    Self.Tell(ExecutionContext.ProcessingMessage, ExecutionContext.ProcessingMessageSender);
                    Behavior.Become(TransitingProcessBehavior, nameof(TransitingProcessBehavior));
                    ExecutionContext.Clear();
                });
                StashingMessagesToProcessBehavior("process is waiting for process instance creation");
            }
        }
        public async Task ProcessPipeActor_routes_events_by_type()
        {
            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 = new MessageMetadataEnvelop <DomainEvent>(new BalloonCreated("1", Guid.NewGuid().ToString()),
                                                               MessageMetadata.Empty);

            processPipeActor.Tell(msg);

            //TestActor from test process processor receives message after work is done
            ExpectMsg <ProcessTransited>();
            //process pipe should send next step - command execution actor that new commands should be executed
            ExpectMsg <IMessageMetadataEnvelop <ICommand> >();
        }
        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>();
        }
예제 #26
0
        public async Task <object> Execute(CommandPlan plan)
        {
            var waiter = new AkkaCommandLocalWaiter(this, _system, _transport, plan.Timeout, true);

            var expectBuilder = waiter.ExpectBuilder;

            //All expected messages should be received
            foreach (var expectedMessage in plan.ExpectedMessages.Where(e => !typeof(IFault).IsAssignableFrom(e.MessageType)))
            {
                expectBuilder.And(MessageMetadataEnvelop.GenericForType(expectedMessage.MessageType),
                                  o => expectedMessage.Match((o as IMessageMetadataEnvelop)?.Message));
            }


            //All expected faults should end waiting
            foreach (var expectedMessage in plan.ExpectedMessages.Where(e => typeof(IFault).IsAssignableFrom(e.MessageType)))
            {
                expectBuilder.Or(MessageMetadataEnvelop.GenericForType(expectedMessage.MessageType),
                                 o => expectedMessage.Match((o as IMessageMetadataEnvelop)?.Message) &&
                                 (!expectedMessage.Sources.Any() ||
                                  expectedMessage.Sources.Contains(((o as IMessageMetadataEnvelop)?.Message as IFault)?.Processor)));
            }

            //Command fault should always end waiting
            var commandFaultType = typeof(IFault <>).MakeGenericType(plan.Command.GetType());

            expectBuilder.Or(MessageMetadataEnvelop.GenericForType(commandFaultType),
                             o => (((o as IMessageMetadataEnvelop)?.Message as IFault)?.Message as ICommand)?.Id == plan.Command.Id);


            var res = await expectBuilder.Create(plan.Timeout)
                      .Execute(plan.Command)
                      .ConfigureAwait(false);

            return(res.All.Count > 1 ? res.All.ToArray() : res.All.FirstOrDefault());
        }
        public void When_child_revives_monitor_should_be_created_even_on_collision()
        {
            var ChildId = "testChild";

            var create = new MessageMetadataEnvelop <ICommand>(new InflateNewBallonCommand(42, ChildId),
                                                               MessageMetadata.New(ChildId, null, null));

            _hubRef.Tell(create);

            Task.Run(async() =>
            {
                while (true)
                {
                    var activate = new MessageMetadataEnvelop <ICommand>(new WriteTitleCommand(100, ChildId),
                                                                         MessageMetadata.New(ChildId, null, null));

                    _hubRef.Tell(activate);
                    await Task.Delay(150);
                }
            });

            EventFilter.Exception <InvalidActorNameException>()
            .Expect(0, TimeSpan.FromSeconds(10), () => { });
        }
 public void Publish(object msg, IMessageMetadata metadata)
 {
     _log.Trace("Publishing {@Message} to transport with metadata {@metadata}", msg, metadata);
     _bus.Publish(MessageMetadataEnvelop.NewGeneric(msg, metadata));
 }
        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>();
        }
예제 #30
0
 public void Publish(object msg, IMessageMetadata metadata)
 {
     Publish(MessageMetadataEnvelop.NewGeneric(msg, metadata));
 }