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); } }
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) }); }
public void SagaContextRequired() { var saga = new FakeSaga(); var e = new FakeEvent(); Assert.Throws<InvalidOperationException>(() => saga.Handle(e)); }
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)); } }
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); }
public void SagaContextIsRequired() { var saga = new FakeSaga(); var ex = Assert.Throws <InvalidOperationException>(() => saga.Handle(new FakeEvent())); Assert.Equal(Exceptions.NoSagaContext, ex.Message); }
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); }
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); }
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 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 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); }
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()); }
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); }
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); } }
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 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); }
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); }
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); }
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); }
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()); } }
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); } }
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 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); } }
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)); } }
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); }
public void SagaContextIsRequired() { var saga = new FakeSaga(); var ex = Assert.Throws<InvalidOperationException>(() => saga.Handle(new FakeEvent())); Assert.Equal(Exceptions.NoSagaContext, ex.Message); }
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 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 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 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)); } }