Пример #1
0
        public async Task SagaStore_SaveAsyncWhenPendingCommandsPutThemToBusIfExceptionThrownSagaPersisted()
        {
            var options = PopulateContext();

            using (var context = new InfrastructureContext(options))
            {
                var mockBus = new Mock <ICommandBus>();
                mockBus.SetupSequence(s => s.SendCommandAsync <Command>(It.IsAny <FakeCommand>()))
                .Returns(Task.CompletedTask)
                .Throws(new DbUpdateException("Cannot save entity in db. Connection closed", new Exception()));

                var saga = new FakeSaga {
                    Id = Guid.Empty, PendingCommands = { new FakeCommand(), new FakeCommand() }
                };
                var sut = new SagaStore(mockBus.Object, Mock.Of <ISagaSerializer>(), context);

                await Assert.ThrowsAsync <DbUpdateException>(async() => await sut.SaveAsync(saga));

                Assert.Equal(1, saga.PendingCommands.Count);
            }

            using (var context = new InfrastructureContext(options))
            {
                var sagaEntity = context.Sagas.FindAsync(Guid.Empty, typeof(SagaStore).FullName);

                Assert.NotNull(sagaEntity);
            }
        }
Пример #2
0
        private SagaEntity GenerateSagaEntity(Guid sagaId, bool completed = false, bool pendingCommands = false)
        {
            var correlationId = Guid.NewGuid();
            var saga          = new FakeSaga {
                Id              = sagaId,
                Completed       = completed,
                CorrelationId   = correlationId,
                PendingCommands =
                {
                    new FakeCommand
                    {
                    }
                }
            };

            if (!pendingCommands)
            {
                saga.PendingCommands?.Clear();
            }

            var json = JsonConvert.SerializeObject(saga, Formatting.Indented, new JsonSerializerSettings {
                TypeNameHandling = TypeNameHandling.All
            });

            return(new SagaEntity
            {
                CorrelationId = correlationId,
                Id = sagaId,
                Completed = completed,
                Type = typeof(FakeSaga).AssemblyQualifiedName,
                FullName = typeof(FakeSaga).FullName,
                Payload = Encoding.UTF8.GetBytes(json)
            });
        }
Пример #3
0
            public void SagaContextRequired()
            {
                var saga = new FakeSaga();
                var e = new FakeEvent();

                Assert.Throws<InvalidOperationException>(() => saga.Handle(e));
            }
Пример #4
0
        public async Task SagaStore_SaveAsyncInvokesSerializeOnISagaSerializer()
        {
            var options = PopulateContext();

            using (var context = new InfrastructureContext(options))
            {
                var stubSagaSerializer = new Mock <ISagaSerializer>();

                stubSagaSerializer.Setup(s => s.Serialize(It.IsAny <FakeSaga>()))
                .Returns <FakeSaga>((s) =>
                {
                    var payload = JsonConvert.SerializeObject(
                        s,
                        new JsonSerializerSettings
                    {
                        TypeNameHandling = TypeNameHandling.All
                    });

                    return(Encoding.UTF8.GetBytes(payload));
                });

                var saga = new FakeSaga {
                    Id = Guid.Empty
                };
                var sut = new SagaStore(Mock.Of <ICommandBus>(), stubSagaSerializer.Object, context);

                await sut.SaveAsync(saga);

                stubSagaSerializer.Verify(v => v.Serialize(saga));
            }
        }
Пример #5
0
            public void SagaContextRequired()
            {
                var saga = new FakeSaga();
                var e    = new FakeEvent();

                Assert.Throws <InvalidOperationException>(() => saga.Handle(e));
            }
        static ActiveSagaInstance AssociateSagaWithMessage(FakeSaga saga, IInvokeHandlerContext behaviorContext)
        {
            var sagaInstance = new ActiveSagaInstance(saga, SagaMetadata.Create(typeof(FakeSaga), new List <Type>(), new Conventions()), () => DateTime.UtcNow);

            behaviorContext.Extensions.Set(sagaInstance);
            return(sagaInstance);
        }
Пример #7
0
            public void SagaContextIsRequired()
            {
                var saga = new FakeSaga();
                var ex   = Assert.Throws <InvalidOperationException>(() => saga.Handle(new FakeEvent()));

                Assert.Equal(Exceptions.NoSagaContext, ex.Message);
            }
Пример #8
0
            public void FlagSagaAsCompleteOnMarkCompleted()
            {
                var saga = new FakeSaga();

                saga.Handle(new FakeEvent());

                Assert.True(saga.Completed);
            }
Пример #9
0
            public void FlagSagaAsCompleteOnMarkCompleted()
            {
                var saga = new FakeSaga();

                saga.Handle(new FakeEvent());

                Assert.True(saga.Completed);
            }
            public void DoNotScheduleTimeoutIfTimeoutHasNotChanged()
            {
                var saga = new FakeSaga { Timeout = null };

                using (var context = new SagaContext(typeof(FakeSaga), GuidStrategy.NewGuid(), new FakeEvent()))
                    timeoutDispatcher.PostSave(saga, context, null);

                Assert.False(timer.Changed);
            }
Пример #11
0
            public void CannotClearTimeoutIfNotScheduled()
            {
                var saga = new FakeSaga {
                    CorrelationId = GuidStrategy.NewGuid(), Timeout = null
                };
                var ex = Assert.Throws <InvalidOperationException>(() => saga.Handle(new FakeEvent()));

                Assert.Equal(Exceptions.SagaTimeoutNotScheduled.FormatWith(saga.GetType(), saga.CorrelationId), ex.Message);
            }
Пример #12
0
            public void CannotRescheduleIfTimeoutNotAlreadyScheduled()
            {
                var e    = new FakeEvent();
                var saga = new FakeSaga {
                    Timeout = null
                };

                using (new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                    Assert.Throws <InvalidOperationException>(() => saga.Handle(e));
            }
            protected Saga ConfigureSagaTimeout(DateTime?timeout)
            {
                Saga saga = new FakeSaga();

                saga.Timeout       = timeout;
                saga.CorrelationId = GuidStrategy.NewGuid();
                SagaStore.Setup(mock => mock.TryGetSaga(saga.GetType(), saga.CorrelationId, out saga)).Returns(true);

                return(saga);
            }
            protected UsingSagaEventHandlerBase()
            {
                var sagaMetadata     = new FakeSaga().GetMetadata();
                var commandPublisher = new Mock <IPublishCommands>();
                var executor         = new Action <Object, Event>((handler, e) => { ((FakeSaga)handler).Handle((Timeout)e); Handled = true; });
                var eventHandler     = new EventHandler(typeof(FakeSaga), typeof(Timeout), executor, () => { throw new NotSupportedException(); });

                SystemTime.ClearOverride();
                SagaEventHandler = new SagaTimeoutHandler(eventHandler, sagaMetadata, SagaStore.Object, new Lazy <IPublishCommands>(() => commandPublisher.Object));
            }
            protected Saga ConfigureSagaTimeout(DateTime? timeout)
            {
                Saga saga = new FakeSaga();

                saga.Timeout = timeout;
                saga.CorrelationId = GuidStrategy.NewGuid();
                SagaStore.Setup(mock => mock.TryGetSaga(saga.GetType(), saga.CorrelationId, out saga)).Returns(true);

                return saga;
            }
            protected UsingSagaEventHandlerBase()
            {
                var sagaMetadata = new FakeSaga().GetMetadata();
                var commandPublisher = new Mock<IPublishCommands>();
                var executor = new Action<Object, Event>((handler, e) => { ((FakeSaga)handler).Handle((Timeout)e); Handled = true; });
                var eventHandler = new EventHandler(typeof(FakeSaga), typeof(Timeout), executor, () => { throw new NotSupportedException(); });

                SystemTime.ClearOverride();
                SagaEventHandler = new SagaTimeoutHandler(eventHandler, sagaMetadata, SagaStore.Object, new Lazy<IPublishCommands>(() => commandPublisher.Object));
            }
            public void CommandsNotPublishedOnFailedSave()
            {
                var saga = new FakeSaga();

                SagaStore.Setup(mock => mock.CreateSaga(typeof(FakeSaga), SagaId)).Returns(saga);
                SagaStore.Setup(mock => mock.Save(saga, It.IsAny<SagaContext>())).Throws(new Exception());

                Assert.Throws<Exception>(() => SagaEventHandler.Handle(EventContext));

                CommandPublisher.Verify(mock => mock.Publish(HeaderCollection.Empty, It.IsAny<CommandEnvelope>()), Times.Never());
            }
            public void DoNotScheduleTimeoutIfTimeoutHasNotChanged()
            {
                var saga = new FakeSaga {
                    Timeout = null
                };

                using (var context = new SagaContext(typeof(FakeSaga), GuidStrategy.NewGuid(), new FakeEvent()))
                    timeoutDispatcher.PostSave(saga, context, null);

                Assert.False(timer.Changed);
            }
Пример #19
0
            public void EventContextIsRequired()
            {
                var saga = new FakeSaga();

                using (new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), new FakeEvent()))
                {
                    var ex = Assert.Throws <InvalidOperationException>(() => saga.Handle(new FakeEvent()));

                    Assert.Equal(Exceptions.NoEventContext, ex.Message);
                }
            }
Пример #20
0
            public void TimeoutUpperBoundIsExclusive()
            {
                var timeout = DateTime.Now.AddMinutes(20);
                var saga    = new FakeSaga {
                    Version = 0, Timeout = timeout
                };

                SagaStore.Save(saga, SagaContext);

                Assert.Equal(0, SagaStore.GetScheduledTimeouts(timeout).Count);
            }
Пример #21
0
            public void DoNotInsertNewSagaIfCompleted()
            {
                var saga = new FakeSaga {
                    Version = 0, Completed = true
                };
                var result = default(Saga);

                SagaStore.Save(saga, SagaContext);

                Assert.False(SagaStore.TryGetSaga(typeof(FakeSaga), saga.CorrelationId, out result));
            }
            public void CommandsNotPublishedOnFailedSave()
            {
                var saga = new FakeSaga();

                SagaStore.Setup(mock => mock.CreateSaga(typeof(FakeSaga), SagaId)).Returns(saga);
                SagaStore.Setup(mock => mock.Save(saga, It.IsAny <SagaContext>())).Throws(new Exception());

                Assert.Throws <Exception>(() => SagaEventHandler.Handle(EventContext));

                CommandPublisher.Verify(mock => mock.Publish(HeaderCollection.Empty, It.IsAny <CommandEnvelope>()), Times.Never());
            }
Пример #23
0
            public void IncrementVersionIfSaveSuccessful()
            {
                var saga = new FakeSaga {
                    CorrelationId = SagaId, Version = 0
                };
                var savedSaga = default(Saga);

                SagaStore.Save(saga, SagaContext);

                Assert.True(SagaStore.TryGetSaga(typeof(FakeSaga), SagaId, out savedSaga));
                Assert.Equal(1, saga.Version);
            }
Пример #24
0
            public void CanScheduleTimeoutIfNotScheduled()
            {
                var saga = new FakeSaga();
                var e    = new FakeEvent();

                using (var context = new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                {
                    saga.Handle(e);

                    Assert.NotNull(saga.Timeout);
                    Assert.True(context.TimeoutChanged);
                }
            }
Пример #25
0
            public void TimeoutRepresentedAsUtcDateTime()
            {
                var saga = new FakeSaga();
                var e    = new FakeEvent();

                using (var context = new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                {
                    saga.Handle(e);

                    Assert.Equal(DateTimeKind.Utc, saga.Timeout.GetValueOrDefault().Kind);
                    Assert.True(context.TimeoutChanged);
                }
            }
Пример #26
0
            public void CanScheduleTimeoutIfNotScheduled()
            {
                var saga = new FakeSaga();
                var e = new FakeEvent();

                using (var context = new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                {
                    saga.Handle(e);

                    Assert.NotNull(saga.Timeout);
                    Assert.True(context.TimeoutChanged);
                }
            }
Пример #27
0
            public void ThrowConcurrencyExceptionIfSagaVersionOutOfSync()
            {
                var saga1 = new FakeSaga {
                    CorrelationId = SagaId, Version = 0
                };
                var saga2 = new FakeSaga {
                    CorrelationId = SagaId, Version = 2
                };

                SagaStore.Save(saga1, SagaContext);

                Assert.Throws <ConcurrencyException>(() => SagaStore.Save(saga2, SagaContext));
            }
            public void DoNotUpdateTimerIfClearedTimeoutWasNotNextTimeout()
            {
                var saga = new FakeSaga {
                    CorrelationId = GuidStrategy.NewGuid(), Timeout = null
                };

                using (var context = new SagaContext(sagaTimeout.SagaType, saga.CorrelationId, new FakeEvent()))
                {
                    context.TimeoutChanged = true;
                    timeoutDispatcher.PostSave(saga, context, null);
                }

                Assert.False(timer.Changed);
            }
            public void DoNotUpdateTimerIfScheduledTimeoutAfterNextCachedTimeout()
            {
                var saga = new FakeSaga {
                    CorrelationId = GuidStrategy.NewGuid(), Timeout = SystemTime.Now.AddMinutes(6)
                };

                using (var context = new SagaContext(saga.GetType(), saga.CorrelationId, new FakeEvent()))
                {
                    context.TimeoutChanged = true;
                    timeoutDispatcher.PostSave(saga, context, null);
                }

                Assert.False(timer.Changed);
            }
Пример #30
0
        public async Task SagaIsFoundProcessMessage()
        {
            var handlerInvoked = false;
            var saga           = new FakeSaga();

            var messageHandler  = CreateMessageHandler((i, m, ctx) => handlerInvoked = true, saga);
            var behaviorContext = CreateBehaviorContext(messageHandler);

            AssociateSagaWithMessage(saga, behaviorContext);

            await Sut.Invoke(behaviorContext, _ => Task.CompletedTask);

            handlerInvoked.Should().BeTrue();
        }
            public void UpdateTimerIfClearedTimeoutWasNextTimeout()
            {
                var saga = new FakeSaga {
                    CorrelationId = sagaTimeout.SagaId, Timeout = null
                };

                using (var context = new SagaContext(sagaTimeout.SagaType, sagaTimeout.SagaId, new FakeEvent()))
                {
                    context.TimeoutChanged = true;
                    timeoutDispatcher.PostSave(saga, context, null);
                }

                Assert.True(timer.Changed);
            }
            public void DoNotScheduleTimeoutIfErrorNotNull()
            {
                var saga = new FakeSaga {
                    Timeout = null
                };

                using (var context = new SagaContext(typeof(FakeSaga), GuidStrategy.NewGuid(), new FakeEvent()))
                {
                    context.TimeoutChanged = true;
                    timeoutDispatcher.PostSave(saga, context, new Exception());
                }

                Assert.False(timer.Changed);
            }
Пример #33
0
            public void RemoveSagaIfCompleted()
            {
                var saga = new FakeSaga {
                    CorrelationId = SagaId, Version = 0
                };
                var savedSaga = default(Saga);

                SagaStore.Save(saga, SagaContext);

                saga.Completed = true;

                SagaStore.Save(saga, SagaContext);

                Assert.False(SagaStore.TryGetSaga(typeof(FakeSaga), SagaId, out savedSaga));
            }
            public void ScheduleTimeoutIfTimeoutHasValueAndSagaNotCompleted()
            {
                var saga = new FakeSaga {
                    CorrelationId = GuidStrategy.NewGuid(), Timeout = SystemTime.Now.AddMinutes(1)
                };
                var cachedItems = timeoutDispatcher.TimeoutCache.Count + 1;

                using (var context = new SagaContext(saga.GetType(), saga.CorrelationId, new FakeEvent()))
                {
                    context.TimeoutChanged = true;
                    timeoutDispatcher.PostSave(saga, context, null);
                }

                Assert.Equal(cachedItems, timeoutDispatcher.TimeoutCache.Count);
            }
Пример #35
0
            public void TimeoutContainsAllNonStateData()
            {
                var timeout = DateTime.Now.AddMinutes(20);
                var saga    = new FakeSaga {
                    CorrelationId = GuidStrategy.NewGuid(), Version = 0, Timeout = timeout
                };

                SagaStore.Save(saga, SagaContext);

                var sagaTimeout = SagaStore.GetScheduledTimeouts(timeout.AddMinutes(1)).Single();

                Assert.Equal(saga.CorrelationId, sagaTimeout.SagaId);
                Assert.Equal(saga.GetType(), sagaTimeout.SagaType);
                Assert.Equal(saga.Timeout, sagaTimeout.Timeout);
            }
        public async Task When_saga_found_and_handler_is_saga_should_invoke_handler()
        {
            var handlerInvoked = false;
            var terminator     = new InvokeHandlerTerminator();
            var saga           = new FakeSaga();

            var messageHandler  = CreateMessageHandler((i, m, ctx) => handlerInvoked = true, saga);
            var behaviorContext = CreateBehaviorContext(messageHandler);

            AssociateSagaWithMessage(saga, behaviorContext);

            await terminator.Invoke(behaviorContext, _ => Task.CompletedTask);

            Assert.IsTrue(handlerInvoked);
        }
Пример #37
0
        public async Task SagaNotFoundAndHandlerIsSaga()
        {
            var handlerInvoked = false;
            var saga           = new FakeSaga();

            var messageHandler  = CreateMessageHandler((i, m, ctx) => handlerInvoked = true, saga);
            var behaviorContext = CreateBehaviorContext(messageHandler);
            var sagaInstance    = AssociateSagaWithMessage(saga, behaviorContext);

            sagaInstance.GetType().GetMethod("MarkAsNotFound", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(sagaInstance, new object[] { });

            await Sut.Invoke(behaviorContext, _ => Task.CompletedTask);

            handlerInvoked.Should().BeFalse();
        }
            public void CacheAndReuseExistingSaga()
            {
                var sagaStore = new Mock<IStoreSagas>();
                var sagaId = GuidStrategy.NewGuid();

                using (var cachedSagaStore = new CachedSagaStore(sagaStore.Object))
                {
                    Saga cachedSaga = new FakeSaga();

                    sagaStore.Setup(mock => mock.TryGetSaga(typeof(Saga), sagaId, out cachedSaga)).Returns(true);

                    Assert.True(cachedSagaStore.TryGetSaga(typeof(Saga), sagaId, out cachedSaga));
                    Assert.True(cachedSagaStore.TryGetSaga(typeof(Saga), sagaId, out cachedSaga));

                    sagaStore.Verify(mock => mock.TryGetSaga(typeof(Saga), sagaId, out cachedSaga), Times.Once());
                }
            }
Пример #39
0
            public void CanRescheduleIfTimeoutAlreadyScheduled()
            {
                var e = new FakeEvent();
                var timeout = SystemTime.Now;
                var saga = new FakeSaga { Timeout = timeout };

                using (var context = new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                {
                    saga.Handle(e);

                    Assert.NotEqual(timeout, saga.Timeout);
                    Assert.True(context.TimeoutChanged);
                }
            }
Пример #40
0
            public void CannotRescheduleIfTimeoutNotAlreadyScheduled()
            {
                var e = new FakeEvent();
                var saga = new FakeSaga { Timeout = null };

                using (new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                    Assert.Throws<InvalidOperationException>(() => saga.Handle(e));
            }
            public void ThrowConcurrencyExceptionIfSagaAlreadyExists()
            {
                var saga1 = new FakeSaga { CorrelationId = SagaId, Version = 0 };
                var saga2 = new FakeSaga { CorrelationId = SagaId, Version = 0 };

                SagaStore.Save(saga1, SagaContext);

                Assert.Throws<ConcurrencyException>(() => SagaStore.Save(saga2, SagaContext));
            }
            public void ThrowKeyNotFoundIfSagaTypeUnknown()
            {
                var timeout = DateTime.Now.AddMinutes(20);
                var saga = new FakeSaga { CorrelationId = GuidStrategy.NewGuid(), Version = 0, Timeout = timeout };
                var state = Serializer.Serialize(saga);

                using (var command = Dialect.CreateCommand(Dialect.InsertSaga))
                {
                    command.Parameters.Add(Dialect.CreateTypeIdParameter(Guid.NewGuid()));
                    command.Parameters.Add(Dialect.CreateIdParameter(saga.CorrelationId));
                    command.Parameters.Add(Dialect.CreateTimeoutParameter(timeout));
                    command.Parameters.Add(Dialect.CreateStateParameter(state));

                    Dialect.ExecuteNonQuery(command);
                }

                Assert.Throws<KeyNotFoundException>(() => SagaStore.GetScheduledTimeouts(timeout.AddMinutes(1)));
            }
            public void TimeoutUpperBoundIsExclusive()
            {
                var timeout = DateTime.Now.AddMinutes(20);
                var saga = new FakeSaga { Version = 0, Timeout = timeout };

                SagaStore.Save(saga, SagaContext);

                Assert.Equal(0, SagaStore.GetScheduledTimeouts(timeout).Count);
            }
Пример #44
0
            public void CopyRemoteAddressHeaderFromEventContextIfNoUserAddress()
            {
                var saga = new FakeSaga();
                var userAddress = IPAddress.Loopback.ToString();
                var e = new FakeEvent { Id = GuidStrategy.NewGuid() };
                var headers = new HeaderCollection(new Dictionary<String, string> { { Header.RemoteAddress, userAddress } });

                using (new EventContext(e.Id, headers, e))
                using (var sagaContext = new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                {
                    saga.Handle(new FakeEvent());

                    Assert.Equal(userAddress, sagaContext.GetPublishedCommands().Single().Headers.Single().Value);
                }
            }
Пример #45
0
            public void CopyUserNameHeaderFromEventContext()
            {
                var saga = new FakeSaga();
                var userName = Guid.NewGuid().ToString();
                var e = new FakeEvent { Id = GuidStrategy.NewGuid() };
                var headers = new HeaderCollection(new Dictionary<String, string> { { Header.UserName, userName } });

                using (new EventContext(e.Id, headers, e))
                using (var sagaContext = new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                {
                    saga.Handle(new FakeEvent());

                    Assert.Equal(userName, sagaContext.GetPublishedCommands().Single().Headers.Single().Value);
                }
            }
            public void SagaRemovedFromCacheIfConcurrencyExceptionThrown()
            {
                var saga = new FakeSaga { CorrelationId = GuidStrategy.NewGuid() };
                var sagaStore = new Mock<IStoreSagas>();
                var cachedSaga = default(Saga);
                var save = 0;

                using (var sagaContext = new SagaContext(typeof(FakeSaga), saga.CorrelationId, new FakeEvent()))
                using (var cachedSagaStore = new CachedSagaStore(sagaStore.Object))
                {
                    sagaStore.Setup(mock => mock.Save(It.IsAny<Saga>(), sagaContext)).Callback(() => { if (save++ == 1) { throw new ConcurrencyException(); } });
                    cachedSagaStore.Save(saga, sagaContext);

                    Assert.True(cachedSagaStore.TryGetSaga(typeof(FakeSaga), saga.CorrelationId, out cachedSaga));
                    Assert.Throws<ConcurrencyException>(() => cachedSagaStore.Save(saga, sagaContext));
                    Assert.False(cachedSagaStore.TryGetSaga(typeof(FakeSaga), saga.CorrelationId, out cachedSaga));
                }
            }
Пример #47
0
            public void CannotClearTimeoutIfNotScheduled()
            {
                var saga = new FakeSaga { CorrelationId = GuidStrategy.NewGuid(), Timeout = null };
                var ex = Assert.Throws<InvalidOperationException>(() => saga.Handle(new FakeEvent()));

                Assert.Equal(Exceptions.SagaTimeoutNotScheduled.FormatWith(saga.GetType(), saga.CorrelationId), ex.Message);
            }
Пример #48
0
            public void SagaContextIsRequired()
            {
                var saga = new FakeSaga();
                var ex = Assert.Throws<InvalidOperationException>(() => saga.Handle(new FakeEvent()));

                Assert.Equal(Exceptions.NoSagaContext, ex.Message);
            }
Пример #49
0
            public void CanClearTimeoutIfScheduled()
            {
                var saga = new FakeSaga { Timeout = SystemTime.Now };
                var e = new FakeEvent();

                using (var context = new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                {
                    saga.Handle(e);

                    Assert.Null(saga.Timeout);
                    Assert.True(context.TimeoutChanged);
                }
            }
            public void RemoveSagaIfCompleted()
            {
                var saga = new FakeSaga { CorrelationId = SagaId, Version = 0 };
                var savedSaga = default(Saga);

                SagaStore.Save(saga, SagaContext);

                saga.Completed = true;

                SagaStore.Save(saga, SagaContext);

                Assert.False(SagaStore.TryGetSaga(typeof(FakeSaga), SagaId, out savedSaga));
            }
Пример #51
0
            public void EventContextIsRequired()
            {
                var saga = new FakeSaga();

                using (new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), new FakeEvent()))
                {
                    var ex = Assert.Throws<InvalidOperationException>(() => saga.Handle(new FakeEvent()));

                    Assert.Equal(Exceptions.NoEventContext, ex.Message);
                }
            }
            public void AlwaysReturnCopyOfCachedSaga()
            {
                var sagaStore = new Mock<IStoreSagas>();
                var sagaId = GuidStrategy.NewGuid();

                using (var cachedSagaStore = new CachedSagaStore(sagaStore.Object))
                {
                    Saga cachedSaga = new FakeSaga(), result1, result2;

                    sagaStore.Setup(mock => mock.TryGetSaga(typeof(Saga), sagaId, out cachedSaga)).Returns(true);

                    Assert.True(cachedSagaStore.TryGetSaga(typeof(Saga), sagaId, out result1));
                    Assert.True(cachedSagaStore.TryGetSaga(typeof(Saga), sagaId, out result2));
                    Assert.NotSame(result1, result2);
                }
            }
            public void TimeoutContainsAllNonStateData()
            {
                var timeout = DateTime.Now.AddMinutes(20);
                var saga = new FakeSaga { CorrelationId = GuidStrategy.NewGuid(), Version = 0, Timeout = timeout };

                SagaStore.Save(saga, SagaContext);

                var sagaTimeout = SagaStore.GetScheduledTimeouts(timeout.AddMinutes(1)).Single();
                Assert.Equal(saga.CorrelationId, sagaTimeout.SagaId);
                Assert.Equal(saga.GetType(), sagaTimeout.SagaType);
                Assert.Equal(saga.Timeout, sagaTimeout.Timeout);
            }
Пример #54
0
            public void PreferCustomHeaderOverEventContextHeaderIfDefined()
            {
                var saga = new FakeSaga();
                var userName = Guid.NewGuid().ToString();
                var customUserName = Guid.NewGuid().ToString();
                var e = new FakeEvent { Id = GuidStrategy.NewGuid() };
                var headers = new HeaderCollection(new Dictionary<String, string> { { Header.UserName, userName } });

                using (new EventContext(e.Id, headers, e))
                using (var sagaContext = new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                {
                    saga.Handle(new FakeEvent { CustomHeaders = new[] { new Header(Header.UserName, customUserName, checkReservedNames: false) } });

                    Assert.Equal(customUserName, sagaContext.GetPublishedCommands().Single().Headers.Single().Value);
                }
            }
            public void DoNotInsertNewSagaIfCompleted()
            {
                var saga = new FakeSaga { Version = 0, Completed = true };
                var result = default(Saga);

                SagaStore.Save(saga, SagaContext);

                Assert.False(SagaStore.TryGetSaga(typeof(FakeSaga), saga.CorrelationId, out result));
            }
Пример #56
0
            public void TimeoutRepresentedAsUtcDateTime()
            {
                var saga = new FakeSaga();
                var e = new FakeEvent();

                using (var context = new SagaContext(typeof(Saga), GuidStrategy.NewGuid(), e))
                {
                    saga.Handle(e);

                    Assert.Equal(DateTimeKind.Utc, saga.Timeout.GetValueOrDefault().Kind);
                    Assert.True(context.TimeoutChanged);
                }
            }
            public void IncrementVersionIfSaveSuccessful()
            {
                var saga = new FakeSaga { CorrelationId = SagaId, Version = 0 };
                var savedSaga = default(Saga);

                SagaStore.Save(saga, SagaContext);
                SagaStore.Save(saga, SagaContext);

                Assert.True(SagaStore.TryGetSaga(typeof(FakeSaga), SagaId, out savedSaga));
                Assert.Equal(2, saga.Version);
            }
            public void SagaUpdatedAfterSaveIfNotCompleted()
            {
                var saga = new FakeSaga { CorrelationId = GuidStrategy.NewGuid() };
                var memoryCache = new MemoryCache(Guid.NewGuid().ToString());
                var sagaStore = new Mock<IStoreSagas>();

                using (var sagaContext = new SagaContext(typeof(FakeSaga), saga.CorrelationId, new FakeEvent()))
                using (var cachedSagaStore = new CachedSagaStore(sagaStore.Object, TimeSpan.FromMinutes(1), memoryCache))
                {
                    cachedSagaStore.Save(saga, sagaContext);

                    Assert.Same(saga, memoryCache.Get(typeof(FakeSaga).GetFullNameWithAssembly() + '-' + saga.CorrelationId));
                }
            }
            public void ThrowConcurrencyExceptionIfSagaVersionOutOfSync()
            {
                var saga1 = new FakeSaga { CorrelationId = SagaId, Version = 0 };
                var saga2 = new FakeSaga { CorrelationId = SagaId, Version = 2 };

                SagaStore.Save(saga1, SagaContext);

                saga2.Completed = true;

                Assert.Throws<ConcurrencyException>(() => SagaStore.Save(saga2, SagaContext));
            }
            public void SagaRemovedFromCacheIfCompleted()
            {
                var saga = new FakeSaga { CorrelationId = GuidStrategy.NewGuid() };
                var sagaStore = new Mock<IStoreSagas>();
                var cachedSaga = default(Saga);

                using (var sagaContext = new SagaContext(typeof(FakeSaga), saga.CorrelationId, new FakeEvent()))
                using (var cachedSagaStore = new CachedSagaStore(sagaStore.Object))
                {
                    cachedSagaStore.Save(saga, sagaContext);

                    saga.Completed = true;

                    cachedSagaStore.Save(saga, sagaContext);

                    Assert.False(cachedSagaStore.TryGetSaga(typeof(FakeSaga), saga.CorrelationId, out cachedSaga));
                }
            }