public void Given_default_policy() { _sagaId = Guid.NewGuid(); var sagaStartEvent = new GotTiredEvent(_sagaId, Guid.NewGuid(), Guid.NewGuid(), _sagaId); var waiter = GridNode.NewWaiter() .Expect <SagaCreatedEvent <SoftwareProgrammingSaga.States> >() .Create(); Publisher.Publish(sagaStartEvent); waiter.Wait(); var sagaContinueEvent = new CoffeMakeFailedEvent(_sagaId, sagaStartEvent.PersonId, BusinessDateTime.UtcNow, _sagaId); var waiterB = GridNode.NewWaiter() .Expect <SagaTransitionEvent <SoftwareProgrammingSaga.States, SoftwareProgrammingSaga.Triggers> >() .Create(); Publisher.Publish(sagaContinueEvent); waiterB.Wait(); //saving snapshot Thread.Sleep(200); _snapshots = new AggregateSnapshotRepository(AkkaConf.Persistence.JournalConnectionString, GridNode.AggregateFromSnapshotsFactory) .Load <SoftwareProgrammingSagaState>(sagaStartEvent.SagaId); }
public async Task Given_instance_process_When_recovering_from_creation() { var aggregateFactory = new AggregateFactory(); var processId = Guid.NewGuid().ToString(); var data = aggregateFactory.Build <ProcessStateAggregate <SoftwareProgrammingState> >(processId); var process = new SoftwareProgrammingProcess(); var initialState = new SoftwareProgrammingState(processId, process.MakingCoffee.Name); var eventsToReplay = new DomainEvent[] { new ProcessManagerCreated <SoftwareProgrammingState>(initialState, processId) }; data.ApplyEvents(eventsToReplay); var processManager = new SoftwareProgrammingProcess(); //Try to transit process by message, available only in desired state var coffeMakeFailedEvent = new CoffeMakeFailedEvent(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); var dispatchedCommands = await processManager.Transit(data.State, coffeMakeFailedEvent); //process_produce_commands_only_one_command() Assert.Equal(1, dispatchedCommands.Count); //Produced_command_has_right_person_id() var sleepCommand = dispatchedCommands.OfType <GoSleepCommand>().First(); Assert.Equal(coffeMakeFailedEvent.ForPersonId, sleepCommand.PersonId); //Produced_command_has_right_sofa_id() Assert.Equal(data.State.SofaId, sleepCommand.SofaId); //process_produce_command_from_given_state() Assert.IsAssignableFrom <GoSleepCommand>(dispatchedCommands.FirstOrDefault()); }
public async Task When_process_produce_command_and_waiting_for_it_fault() { var givenProcessStateAggregate = new ProcessStateAggregate <SoftwareProgrammingState>(new SoftwareProgrammingState(Guid.NewGuid().ToString(), nameof(SoftwareProgrammingProcess.MakingCoffee)) { PersonId = Guid.NewGuid().ToString() }); await Node.SaveToJournal(givenProcessStateAggregate); var coffeMakeFailedEvent = new CoffeMakeFailedEvent(Guid.NewGuid().ToString(), givenProcessStateAggregate.State.PersonId, BusinessDateTime.UtcNow, givenProcessStateAggregate.Id); await Node.NewDebugWaiter() .Expect <ProcessReceivedMessage <SoftwareProgrammingState> >(m => m.State.CurrentStateName == nameof(SoftwareProgrammingProcess.Coding)) .Create() .SendToProcessManagers(coffeMakeFailedEvent, MessageMetadata.New(coffeMakeFailedEvent.SourceId, null, null)); var processStateAggregate = await this.LoadProcessByActor <SoftwareProgrammingState>(givenProcessStateAggregate.Id); //Process_should_be_in_correct_state_after_fault_handling() Assert.Equal(nameof(SoftwareProgrammingProcess.Coding), processStateAggregate.CurrentStateName); //Process_state_should_contain_data_from_fault_message() Assert.Equal(coffeMakeFailedEvent.ForPersonId, processStateAggregate.BadSleepPersonId); }
public async Task Given_default_policy() { var startEvent = new GotTiredEvent(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); var res = await Node.NewDebugWaiter() .Expect <ProcessManagerCreated <SoftwareProgrammingState> >() .Create() .SendToProcessManagers(startEvent); var processId = res.Message <ProcessManagerCreated <SoftwareProgrammingState> >().SourceId; var continueEvent = new CoffeMakeFailedEvent(Guid.NewGuid().ToString(), startEvent.PersonId, BusinessDateTime.UtcNow, processId); await Node.NewDebugWaiter() .Expect <ProcessReceivedMessage <SoftwareProgrammingState> >() .Create() .SendToProcessManagers(continueEvent); //saving snapshot await Task.Delay(200); var snapshots = await new AggregateSnapshotRepository(AutoTestNodeDbConfiguration.Default.JournalConnectionString, new AggregateFactory(), new AggregateFactory() ).Load <ProcessStateAggregate <SoftwareProgrammingState> >( startEvent.ProcessId); //Snapshot_should_be_saved_one_time() Assert.Empty(snapshots); }
public async Task Given_save_on_each_message_policy_and_keep_2_snapshots() { var startEvent = new GotTiredEvent(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); var res = await Node.NewDebugWaiter() .Expect <ProcessManagerCreated <SoftwareProgrammingState> >() .Create() .SendToProcessManagers(startEvent); var processId = res.Message <ProcessManagerCreated <SoftwareProgrammingState> >() .SourceId; var continueEventA = new CoffeMakeFailedEvent(Guid.NewGuid().ToString(), startEvent.PersonId, BusinessDateTime.UtcNow, processId); await Node.SendToProcessManagers(continueEventA); await Node.KillProcessManager <SoftwareProgrammingProcess, SoftwareProgrammingState>(processId); Version <ProcessStateAggregate <SoftwareProgrammingState> >[] snapshots = null; //Only_two_Snapshots_should_left() AwaitAssert(() => { snapshots = AggregateSnapshotRepository.New(AutoTestNodeDbConfiguration.Default.JournalConnectionString) .Load <ProcessStateAggregate <SoftwareProgrammingState> >(processId) .Result; Assert.Equal(2, snapshots.Length); // Restored_aggregates_should_have_same_ids() Assert.True(snapshots.All(s => s.Payload.Id == processId)); // First_Snapshots_should_have_coding_state_from_first_event() Assert.Equal(nameof(SoftwareProgrammingProcess.MakingCoffee), snapshots.First() .Payload.State.CurrentStateName); //Last_Snapshots_should_have_coding_state_from_last_event() Assert.Equal(nameof(SoftwareProgrammingProcess.Sleeping), snapshots.Last() .Payload.State.CurrentStateName); //All_snapshots_should_not_have_uncommited_events() Assert.Empty(snapshots.SelectMany(s => s.Payload.GetEvents())); }, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(1)); }
public void Given_save_on_each_message_policy_and_keep_2_snapshots() { _sagaId = Guid.NewGuid(); var sagaStartEvent = new GotTiredEvent(_sagaId, Guid.NewGuid(), Guid.NewGuid(), _sagaId); var wait = GridNode.NewWaiter() .Expect <SagaCreatedEvent <SoftwareProgrammingSagaData> >() .Create(); Publisher.Publish(sagaStartEvent); wait.Wait(); var sagaActorRef = LookupInstanceSagaActor <SoftwareProgrammingSaga, SoftwareProgrammingSagaData>(_sagaId); sagaActorRef.Tell(new NotifyOnPersistenceEvents(TestActor), TestActor); var sagaContinueEventA = new CoffeMakeFailedEvent(_sagaId, sagaStartEvent.PersonId, BusinessDateTime.UtcNow, _sagaId); var sagaContinueEventB = new SleptWellEvent(_sagaId, sagaStartEvent.LovelySofaId, _sagaId); var waiter = GridNode.NewWaiter() .Expect <SagaMessageReceivedEvent <SoftwareProgrammingSagaData> >(e => (e.Message as CoffeMakeFailedEvent)?.SourceId == _sagaId) .And <SagaMessageReceivedEvent <SoftwareProgrammingSagaData> >(e => (e.Message as SleptWellEvent)?.SourceId == _sagaId) .Create(); Publisher.Publish(sagaContinueEventA); Publisher.Publish(sagaContinueEventB); waiter.Wait(); Watch(sagaActorRef); sagaActorRef.Tell(GracefullShutdownRequest.Instance, TestActor); FishForMessage <Terminated>(m => true, TimeSpan.FromDays(1)); Thread.Sleep(1000); _snapshots = new AggregateSnapshotRepository(AkkaConf.Persistence.JournalConnectionString, GridNode.AggregateFromSnapshotsFactory) .Load <SagaDataAggregate <SoftwareProgrammingSagaData> >(_sagaId); Console.WriteLine(_snapshotsPersistencePolicy.ToPropsString()); }
public void Given_save_on_each_message_policy_and_keep_2_snapshots() { _sagaId = Guid.NewGuid(); var sagaStartEvent = new GotTiredEvent(_sagaId, Guid.NewGuid(), Guid.NewGuid(), _sagaId); var w = GridNode.NewWaiter() .Expect <SagaCreatedEvent <SoftwareProgrammingSaga.States> >() .Create(); Publisher.Publish(sagaStartEvent); w.Wait(); var sagaActorRef = LookupStateSagaActor <SoftwareProgrammingSaga, SoftwareProgrammingSagaState>(_sagaId); Watch(sagaActorRef); sagaActorRef.Tell(new NotifyOnPersistenceEvents(TestActor), TestActor); var sagaContinueEventA = new CoffeMakeFailedEvent(_sagaId, sagaStartEvent.PersonId, BusinessDateTime.UtcNow, _sagaId); var sagaContinueEventB = new SleptWellEvent(_sagaId, sagaStartEvent.LovelySofaId, _sagaId); var waiter = GridNode.NewWaiter() .Expect <SagaTransitionEvent <SoftwareProgrammingSaga.States, SoftwareProgrammingSaga.Triggers> >(e => e.State == SoftwareProgrammingSaga.States.Coding) .And <SagaTransitionEvent <SoftwareProgrammingSaga.States, SoftwareProgrammingSaga.Triggers> >(e => e.State == SoftwareProgrammingSaga.States.Sleeping) .Create(); Publisher.Publish(sagaContinueEventA); Publisher.Publish(sagaContinueEventB); waiter.Wait(); sagaActorRef.Tell(GracefullShutdownRequest.Instance, TestActor); FishForMessage <Terminated>(m => true); _snapshots = new AggregateSnapshotRepository(AkkaConf.Persistence.JournalConnectionString, GridNode.AggregateFromSnapshotsFactory) .Load <SoftwareProgrammingSagaState>(_sagaId); }
public async Task When_saga_receives_a_message_that_case_saga_exception() { var sagaId = Guid.NewGuid(); var personId = Guid.NewGuid(); //prepare initial saga state var sagaDataEvent = new SagaCreatedEvent <SoftwareProgrammingSaga.States>(SoftwareProgrammingSaga.States.MakingCoffee, sagaId); SaveInJournal <SoftwareProgrammingSagaState>(sagaId, sagaDataEvent); var sagaTransitEvent = new CoffeMakeFailedEvent(Guid.Empty, personId).CloneWithSaga(sagaId); var waitResults = await GridNode.NewDebugWaiter() .Expect <IFault <CoffeMakeFailedEvent> >() .Create() .Publish(sagaTransitEvent); _fault = waitResults.Message <IFault <CoffeMakeFailedEvent> >(); }
public void Given_instance_saga_When_recovering_from_creation() { var aggregateFactory = new AggregateFactory(); var sagaId = Guid.NewGuid(); _data = aggregateFactory.Build <SagaDataAggregate <SoftwareProgrammingSagaData> >(sagaId); var saga = new SoftwareProgrammingSaga(); var initialState = new SoftwareProgrammingSagaData(saga.MakingCoffee.Name); var eventsToReplay = new DomainEvent[] { new SagaCreatedEvent <SoftwareProgrammingSagaData>(initialState, sagaId) }; _data.ApplyEvents(eventsToReplay); _sagaInstance = SagaInstance.New(saga, _data); //Try to transit saga by message, available only in desired state _coffeMakeFailedEvent = new CoffeMakeFailedEvent(Guid.NewGuid(), Guid.NewGuid()); _sagaInstance.Transit(_coffeMakeFailedEvent); _dispatchedCommands = _sagaInstance.CommandsToDispatch; }
public void Process_Faults_Should_be_deserializable() { //CoffeMakeFailedEvent var coffeMakeFailedEvent = new CoffeMakeFailedEvent(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); CheckDeserialize(coffeMakeFailedEvent, nameof(coffeMakeFailedEvent)); var undefinedCoffeMachineException = new UndefinedCoffeMachineException(); CheckDeserialize(undefinedCoffeMachineException, nameof(undefinedCoffeMachineException)); var processTransitionException = new ProcessTransitionException(coffeMakeFailedEvent, undefinedCoffeMachineException); CheckDeserialize(processTransitionException, nameof(processTransitionException)); var eventExecutionException = new EventExecutionException("test", processTransitionException); CheckDeserialize(eventExecutionException, nameof(eventExecutionException)); var msg = new Akka.Actor.Status.Failure(new AggregateException(eventExecutionException)); CheckDeserialize(msg, nameof(msg)); }
public void When_publishing_start_message() { var sagaId = Guid.NewGuid(); _sagaData = new SoftwareProgrammingSagaData(nameof(SoftwareProgrammingSaga.MakingCoffee)) { PersonId = Guid.NewGuid() }; var sagaDataEvent = new SagaCreatedEvent <SoftwareProgrammingSagaData>(_sagaData, sagaId); SaveInJournal <SagaDataAggregate <SoftwareProgrammingSagaData> >(sagaId, sagaDataEvent); Thread.Sleep(100); _coffeMakeFailedEvent = new CoffeMakeFailedEvent(Guid.NewGuid(), Guid.NewGuid(), BusinessDateTime.UtcNow, sagaId); GridNode.Transport.Publish(_coffeMakeFailedEvent, new MessageMetadata(_coffeMakeFailedEvent.SourceId)); //WaitFor<SagaTransitionEvent<SoftwareProgrammingSagaData>>(); //WaitFor<SagaTransitionEvent<SoftwareProgrammingSagaData>>(); Thread.Sleep(1000); _sagaDataAggregate = LoadAggregate <SagaDataAggregate <SoftwareProgrammingSagaData> >(sagaId); }
public async Task Given_default_policy() { var startEvent = new GotTiredEvent(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); var resTask = Node.NewDebugWaiter() .Expect <ProcessReceivedMessage <SoftwareProgrammingState> >() .Create() .SendToProcessManagers(startEvent, MessageMetadata.New(startEvent.Id, null, null)); var processId = (await resTask).Message <ProcessReceivedMessage <SoftwareProgrammingState> >().SourceId; var continueEvent = new CoffeMakeFailedEvent(processId, startEvent.PersonId, BusinessDateTime.UtcNow, processId); //to avoid racy state receiving expected message from processing GotTiredEvent await Node.NewDebugWaiter() .Expect <ProcessReceivedMessage <SoftwareProgrammingState> >(e => e.MessageId == continueEvent.Id) .Create() .SendToProcessManagers(continueEvent, processId); Log.Info("Testcase enforce additional snapshot save & delete, will kill process manager"); await Node.KillProcessManager <SoftwareProgrammingProcess, SoftwareProgrammingState>(processId); var snapshots = await AggregateSnapshotRepository.New(AutoTestNodeDbConfiguration.Default.JournalConnectionString, AggregateFactory.Default) .Load <ProcessStateAggregate <SoftwareProgrammingState> >(processId); //Snapshot_should_be_saved_one_time Assert.Single(snapshots); //Restored_process_state_should_have_correct_ids Assert.True(snapshots.All(s => s.Payload.Id == processId)); //Snapshot_should_have_parameters_from_first_event = created event Assert.Equal(nameof(SoftwareProgrammingProcess.Coding), snapshots.First().Payload.State.CurrentStateName); //All_snapshots_should_not_have_uncommited_events Assert.Empty(snapshots.SelectMany(s => s.Payload.GetEvents())); }
public void Handle(CoffeMakeFailedEvent msg) { TransitState(msg); }
public async Task Given_default_policy() { var startEvent = new GotTiredEvent(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); var res = await Node.NewDebugWaiter() .Expect <ProcessManagerCreated <SoftwareProgrammingState> >() .Create() .SendToProcessManagers(startEvent); var processId = res.Message <ProcessManagerCreated <SoftwareProgrammingState> >() .SourceId; var continueEvent = new CoffeMakeFailedEvent(processId, startEvent.PersonId, BusinessDateTime.UtcNow, processId); await Node.NewDebugWaiter() .Expect <ProcessReceivedMessage <SoftwareProgrammingState> >() .Create() .SendToProcessManagers(continueEvent); var continueEventB = new Fault <GoSleepCommand>(new GoSleepCommand(startEvent.PersonId, startEvent.LovelySofaId), new Exception(), typeof(object), processId, BusinessDateTime.Now); await Node.NewDebugWaiter() .Expect <ProcessReceivedMessage <SoftwareProgrammingState> >() .Create() .SendToProcessManagers(continueEventB); await Node.KillProcessManager <SoftwareProgrammingProcess, SoftwareProgrammingState>(continueEvent.ProcessId); Version <ProcessStateAggregate <SoftwareProgrammingState> >[] snapshots = null; AwaitAssert(() => { snapshots = new AggregateSnapshotRepository(AutoTestNodeDbConfiguration.Default.JournalConnectionString, AggregateFactory.Default, AggregateFactory.Default) .Load <ProcessStateAggregate <SoftwareProgrammingState> >(processId) .Result; //saving on each message, maximum on each command //Snapshots_should_be_saved_two_times //4 events in total, two saves of snapshots due to policy saves on each two events //1 event and 3 Assert.Equal(2, snapshots.Length); //First_snapshot_should_have_state_from_first_event Assert.Equal(nameof(SoftwareProgrammingProcess.Coding), snapshots.First() .Payload.State.CurrentStateName); //Last_snapshot_should_have_parameters_from_last_command() Assert.Equal(nameof(SoftwareProgrammingProcess.Sleeping), snapshots.Last() .Payload.State.CurrentStateName); //Restored_process_state_should_have_correct_ids Assert.True(snapshots.All(s => s.Payload.Id == processId)); //All_snapshots_should_not_have_uncommited_events() Assert.Empty(snapshots.SelectMany(s => s.Payload.GetEvents())); }, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(1)); }