public async Task It_should_successfully_update_the_saga() { var id = Guid.NewGuid(); var sagaData = new SagaWithoutUniquePropertyData { Id = id, NonUniqueString = "whatever" }; var persister = new InMemorySagaPersister(); // first session var session = new InMemorySynchronizedStorageSession(); await persister.Save(sagaData, SagaCorrelationProperty.None, session, new ContextBag()); await session.CompleteAsync(); // second session var session2 = new InMemorySynchronizedStorageSession(); var ctx = new ContextBag(); var saga = await persister.Get<SagaWithoutUniquePropertyData>(id, session2, ctx); saga.NonUniqueString = "asdfasdf"; await persister.Update(saga, session2, ctx); await session2.CompleteAsync(); var result = await persister.Get<SagaWithoutUniquePropertyData>(sagaData.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); Assert.That(result, Is.Not.Null); Assert.That(result.NonUniqueString, Is.EqualTo("asdfasdf")); }
public async Task Save_fails_when_data_changes_between_read_and_update_on_same_thread() { var sagaId = Guid.NewGuid(); var saga = new TestSagaData { Id = sagaId, SomeId = sagaId.ToString() }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata<TestSaga>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var winningContext = new ContextBag(); var record = await persister.Get<TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), winningContext); var losingContext = new ContextBag(); var staleRecord = await persister.Get<TestSagaData>("SomeId", sagaId.ToString(), new InMemorySynchronizedStorageSession(), losingContext); var winningSaveSession = new InMemorySynchronizedStorageSession(); var losingSaveSession = new InMemorySynchronizedStorageSession(); await persister.Update(record, winningSaveSession, winningContext); await persister.Update(staleRecord, losingSaveSession, losingContext); await winningSaveSession.CompleteAsync(); Assert.That(async () => await losingSaveSession.CompleteAsync(), Throws.InstanceOf<Exception>().And.Message.StartsWith($"InMemorySagaPersister concurrency violation: saga entity Id[{saga.Id}] already saved.")); }
public async Task It_should_successfully_remove_the_saga() { var id = Guid.NewGuid(); var sagaData = new SagaWithoutUniquePropertyData { Id = id, NonUniqueString = "whatever" }; var persister = new InMemorySagaPersister(); var savingSession = new InMemorySynchronizedStorageSession(); await persister.Save(sagaData, null, savingSession, new ContextBag()); await savingSession.CompleteAsync(); // second session var completingSession = new InMemorySynchronizedStorageSession(); var completingContextBag = new ContextBag(); var saga = await persister.Get<SagaWithoutUniquePropertyData>(id, completingSession, completingContextBag); await persister.Complete(saga, completingSession, completingContextBag); await completingSession.CompleteAsync(); var result = await persister.Get<SagaWithoutUniquePropertyData>(sagaData.Id, savingSession, new ContextBag()); Assert.That(result, Is.Null); }
async Task SaveSaga(SagaWithUniquePropertyData saga) { using (var session = new InMemorySynchronizedStorageSession()) { var ctx = new ContextBag(); await persister.Save(saga, SagaMetadataHelper.GetMetadata<SagaWithUniqueProperty>(saga), session, ctx); await session.CompleteAsync(); } }
async Task CompleteSaga(Guid sagaId) { using (var session = new InMemorySynchronizedStorageSession()) { var ctx = new ContextBag(); var saga = await persister.Get<SagaWithUniquePropertyData>(sagaId, session, ctx); await persister.Complete(saga, session, ctx); await session.CompleteAsync(); } }
public async Task Should_return_default_when_using_finding_saga_with_id_of_another_type() { var id = Guid.NewGuid(); var simpleSagaEntity = new SimpleSagaEntity { Id = id, OrderSource = "CA" }; var persister = new InMemorySagaPersister(); var session = new InMemorySynchronizedStorageSession(); await persister.Save(simpleSagaEntity, SagaMetadataHelper.GetMetadata<SimpleSagaEntitySaga>(simpleSagaEntity), session, new ContextBag()); await session.CompleteAsync(); var anotherSagaEntity = await persister.Get<AnotherSimpleSagaEntity>(id, new InMemorySynchronizedStorageSession(), new ContextBag()); Assert.IsNull(anotherSagaEntity); }
public async Task Persister_returns_different_instance_of_saga_data() { var saga = new TestSagaData { Id = Guid.NewGuid() }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata<TestSaga>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var returnedSaga1 = await persister.Get<TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); var returnedSaga2 = await persister.Get<TestSagaData>("Id", saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); Assert.AreNotSame(returnedSaga2, returnedSaga1); Assert.AreNotSame(returnedSaga1, saga); Assert.AreNotSame(returnedSaga2, saga); }
public async Task Should_return_default_when_using_finding_saga_with_id_of_another_type() { var id = Guid.NewGuid(); var simpleSagaEntity = new SimpleSagaEntity { Id = id, OrderSource = "CA" }; var persister = new InMemorySagaPersister(); var session = new InMemorySynchronizedStorageSession(); await persister.Save(simpleSagaEntity, SagaMetadataHelper.GetMetadata <SimpleSagaEntitySaga>(simpleSagaEntity), session, new ContextBag()); await session.CompleteAsync(); var anotherSagaEntity = await persister.Get <AnotherSimpleSagaEntity>(id, new InMemorySynchronizedStorageSession(), new ContextBag()); Assert.IsNull(anotherSagaEntity); }
public async Task It_should_persist_successfully() { var saga1 = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var saga2 = new AnotherSagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var persister = new InMemorySagaPersister(); var transaction = new InMemorySynchronizedStorageSession(); await persister.Save(saga1, SagaMetadataHelper.GetMetadata<SagaWithUniqueProperty>(saga1), transaction, new ContextBag()); await persister.Save(saga2, SagaMetadataHelper.GetMetadata<AnotherSagaTwoUniqueProperty>(saga2), transaction, new ContextBag()); await transaction.CompleteAsync(); }
public async Task It_should_persist_successfully() { var saga1 = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var saga2 = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var persister = new InMemorySagaPersister(); using (var session1 = new InMemorySynchronizedStorageSession()) { await persister.Save(saga1, SagaMetadataHelper.GetMetadata <SagaWithUniqueProperty>(saga1), session1, new ContextBag()); await persister.Complete(saga1, session1, new ContextBag()); await session1.CompleteAsync(); } using (var session2 = new InMemorySynchronizedStorageSession()) { await persister.Save(saga2, SagaMetadataHelper.GetMetadata <SagaWithUniqueProperty>(saga2), session2, new ContextBag()); await persister.Complete(saga2, session2, new ContextBag()); await session2.CompleteAsync(); } using (var session3 = new InMemorySynchronizedStorageSession()) { await persister.Save(saga1, SagaMetadataHelper.GetMetadata <SagaWithUniqueProperty>(saga1), session3, new ContextBag()); await persister.Complete(saga1, session3, new ContextBag()); await session3.CompleteAsync(); } }
public async Task Save_fails_when_data_changes_between_concurrent_instances() { var saga = new TestSagaData { Id = Guid.NewGuid() }; var persister = new InMemorySagaPersister(); var storageAdapter = new InMemoryTransactionalSynchronizedStorageAdapter(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata <TestSaga>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); Assert.That(async() => { using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { Transaction.Current.EnlistDurable(EnlistmentWhichEnforcesDtcEscalation.Id, new EnlistmentWhichEnforcesDtcEscalation(), EnlistmentOptions.None); var transportTransaction = new TransportTransaction(); transportTransaction.Set(Transaction.Current); var unenlistedSession = new InMemorySynchronizedStorageSession(); var enlistedSession = await storageAdapter.TryAdapt(transportTransaction, new ContextBag()); var unenlistedSessionContext = new ContextBag(); var unenlistedRecord = await persister.Get <TestSagaData>(saga.Id, unenlistedSession, unenlistedSessionContext); var enlistedSessionContext = new ContextBag(); var enlistedRecord = await persister.Get <TestSagaData>("Id", saga.Id, enlistedSession, enlistedSessionContext); await persister.Update(unenlistedRecord, unenlistedSession, unenlistedSessionContext); await persister.Update(enlistedRecord, enlistedSession, enlistedSessionContext); await unenlistedSession.CompleteAsync(); tx.Complete(); } }, Throws.Exception.TypeOf <TransactionAbortedException>()); }
public async Task Save_process_is_repeatable() { var saga = new TestSagaData { Id = Guid.NewGuid() }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata <TestSaga>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var returnedSaga1 = await Task.Run(() => persister.Get <TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag())); var returnedSaga2 = await persister.Get <TestSagaData>("Id", saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); var winningSaveSession = new InMemorySynchronizedStorageSession(); var losingSaveSession = new InMemorySynchronizedStorageSession(); await persister.Save(returnedSaga1, SagaMetadataHelper.GetMetadata <TestSaga>(saga), winningSaveSession, new ContextBag()); await persister.Save(returnedSaga2, SagaMetadataHelper.GetMetadata <TestSaga>(saga), losingSaveSession, new ContextBag()); await winningSaveSession.CompleteAsync(); Assert.That(async() => await losingSaveSession.CompleteAsync(), Throws.InstanceOf <Exception>().And.Message.StartsWith($"InMemorySagaPersister concurrency violation: saga entity Id[{saga.Id}] already saved.")); var returnedSaga3 = await Task.Run(() => persister.Get <TestSagaData>("Id", saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag())); var returnedSaga4 = await persister.Get <TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); winningSaveSession = new InMemorySynchronizedStorageSession(); losingSaveSession = new InMemorySynchronizedStorageSession(); await persister.Save(returnedSaga4, SagaMetadataHelper.GetMetadata <TestSaga>(saga), winningSaveSession, new ContextBag()); await persister.Save(returnedSaga3, SagaMetadataHelper.GetMetadata <TestSaga>(saga), losingSaveSession, new ContextBag()); await winningSaveSession.CompleteAsync(); Assert.That(async() => await losingSaveSession.CompleteAsync(), Throws.InstanceOf <Exception>().And.Message.StartsWith($"InMemorySagaPersister concurrency violation: saga entity Id[{saga.Id}] already saved.")); }
public async Task It_should_persist_successfully() { var saga1 = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga1, SagaMetadataHelper.GetMetadata<SagaWithUniqueProperty>(saga1), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var updatingContext = new ContextBag(); saga1 = await persister.Get<SagaWithUniquePropertyData>(saga1.Id, new InMemorySynchronizedStorageSession(), updatingContext); var updateSession = new InMemorySynchronizedStorageSession(); await persister.Update(saga1, updateSession, updatingContext); await updateSession.CompleteAsync(); }
public async Task Persister_returns_different_instance_of_saga_data() { var saga = new TestSagaData { Id = Guid.NewGuid() }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata <TestSaga>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var returnedSaga1 = await persister.Get <TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); var returnedSaga2 = await persister.Get <TestSagaData>("Id", saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); Assert.AreNotSame(returnedSaga2, returnedSaga1); Assert.AreNotSame(returnedSaga1, saga); Assert.AreNotSame(returnedSaga2, saga); }
public async Task Save_fails_when_data_changes_between_concurrent_instances() { var saga = new TestSagaData { Id = Guid.NewGuid() }; var persister = new InMemorySagaPersister(); var storageAdapter = new InMemoryTransactionalSynchronizedStorageAdapter(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata<TestSaga>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); Assert.That(async () => { using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { Transaction.Current.EnlistDurable(EnlistmentWhichEnforcesDtcEscalation.Id, new EnlistmentWhichEnforcesDtcEscalation(), EnlistmentOptions.None); var transportTransaction = new TransportTransaction(); transportTransaction.Set(Transaction.Current); var unenlistedSession = new InMemorySynchronizedStorageSession(); var enlistedSession = await storageAdapter.TryAdapt(transportTransaction, new ContextBag()); var unenlistedSessionContext = new ContextBag(); var unenlistedRecord = await persister.Get<TestSagaData>(saga.Id, unenlistedSession, unenlistedSessionContext); var enlistedSessionContext = new ContextBag(); var enlistedRecord = await persister.Get<TestSagaData>("Id", saga.Id, enlistedSession, enlistedSessionContext); await persister.Update(unenlistedRecord, unenlistedSession, unenlistedSessionContext); await persister.Update(enlistedRecord, enlistedSession, enlistedSessionContext); await unenlistedSession.CompleteAsync(); tx.Complete(); } }, Throws.Exception.TypeOf<TransactionAbortedException>()); }
public async Task Should_delete_the_saga() { var saga = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga,SagaMetadataHelper.GetMetadata<SagaWithUniqueProperty>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var intentionallySharedContext = new ContextBag(); var sagaData = await persister.Get<SagaWithUniquePropertyData>(saga.Id, new InMemorySynchronizedStorageSession(), intentionallySharedContext ); var completeSession = new InMemorySynchronizedStorageSession(); await persister.Complete(saga, completeSession, intentionallySharedContext ); await completeSession.CompleteAsync(); var completedSagaData = await persister.Get<SagaWithUniquePropertyData>(saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); Assert.NotNull(sagaData); Assert.Null(completedSagaData); }
public async Task It_should_persist_successfully() { var saga1 = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga1, SagaMetadataHelper.GetMetadata <SagaWithUniqueProperty>(saga1), insertSession, new ContextBag()); await insertSession.CompleteAsync(); saga1 = await persister.Get <SagaWithUniquePropertyData>(saga1.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); var updateSession = new InMemorySynchronizedStorageSession(); await persister.Update(saga1, updateSession, new ContextBag()); await updateSession.CompleteAsync(); }
public async Task It_should_persist_successfully() { var saga1 = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var saga2 = new AnotherSagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var persister = new InMemorySagaPersister(); var transaction = new InMemorySynchronizedStorageSession(); await persister.Save(saga1, SagaMetadataHelper.GetMetadata <SagaWithUniqueProperty>(saga1), transaction, new ContextBag()); await persister.Save(saga2, SagaMetadataHelper.GetMetadata <AnotherSagaTwoUniqueProperty>(saga2), transaction, new ContextBag()); await transaction.CompleteAsync(); }
public async Task It_should_persist_successfully() { var sagaData = new SagaWithoutUniquePropertyData { Id = Guid.NewGuid(), NonUniqueString = "whatever" }; var persister = new InMemorySagaPersister(); using (var session = new InMemorySynchronizedStorageSession()) { await persister.Save(sagaData, null, session, new ContextBag()); await session.CompleteAsync(); } using (var session = new InMemorySynchronizedStorageSession()) { var retrieved = await persister.Get<SagaWithoutUniquePropertyData>(sagaData.Id, session, new ContextBag()); Assert.AreEqual(sagaData.NonUniqueString, retrieved.NonUniqueString); } }
public async Task Should_delete_the_saga() { var saga = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata <SagaWithUniqueProperty>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var sagaData = await persister.Get <SagaWithUniquePropertyData>(saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); var completeSession = new InMemorySynchronizedStorageSession(); await persister.Complete(saga, completeSession, new ContextBag()); await completeSession.CompleteAsync(); var completedSagaData = await persister.Get <SagaWithUniquePropertyData>(saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); Assert.NotNull(sagaData); Assert.Null(completedSagaData); }
public async Task Should_delete_the_saga() { var saga = new TestSagaData { Id = Guid.NewGuid() }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata <TestSaga>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var sagaData = await persister.Get <TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); var deleteSession = new InMemorySynchronizedStorageSession(); await persister.Complete(saga, deleteSession, new ContextBag()); await deleteSession.CompleteAsync(); var completedSaga = await persister.Get <TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), new ContextBag()); Assert.NotNull(sagaData); Assert.Null(completedSaga); }
public async Task It_should_enforce_uniqueness() { var saga1 = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var saga2 = new SagaWithUniquePropertyData { Id = Guid.NewGuid(), UniqueString = "whatever" }; var persister = new InMemorySagaPersister(); var winningSession = new InMemorySynchronizedStorageSession(); var losingSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga1, SagaMetadataHelper.GetMetadata<SagaWithUniqueProperty>(saga1), winningSession, new ContextBag()); await persister.Save(saga2, SagaMetadataHelper.GetMetadata<SagaWithUniqueProperty>(saga1), losingSession, new ContextBag()); await winningSession.CompleteAsync(); Assert.That(async () => await losingSession.CompleteAsync(), Throws.InstanceOf<InvalidOperationException>()); }
public async Task It_should_persist_successfully() { var sagaData = new SagaWithoutUniquePropertyData { Id = Guid.NewGuid(), NonUniqueString = "whatever" }; var persister = new InMemorySagaPersister(); using (var session = new InMemorySynchronizedStorageSession()) { await persister.Save(sagaData, null, session, new ContextBag()); await session.CompleteAsync(); } using (var session = new InMemorySynchronizedStorageSession()) { var retrieved = await persister.Get <SagaWithoutUniquePropertyData>(sagaData.Id, session, new ContextBag()); Assert.AreEqual(sagaData.NonUniqueString, retrieved.NonUniqueString); } }
public async Task Save_process_is_repeatable() { var sagaId = Guid.NewGuid(); var saga = new TestSagaData { Id = sagaId, SomeId = sagaId.ToString() }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata<TestSaga>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var winningSessionContext = new ContextBag(); var returnedSaga1 = await Task.Run(() => persister.Get<TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), winningSessionContext)); var losingSessionContext = new ContextBag(); var returnedSaga2 = await persister.Get<TestSagaData>("SomeId", sagaId.ToString(), new InMemorySynchronizedStorageSession(), losingSessionContext); var winningSaveSession = new InMemorySynchronizedStorageSession(); var losingSaveSession = new InMemorySynchronizedStorageSession(); await persister.Update(returnedSaga1, winningSaveSession, winningSessionContext); await persister.Update(returnedSaga2, losingSaveSession, losingSessionContext); await winningSaveSession.CompleteAsync(); Assert.That(async () => await losingSaveSession.CompleteAsync(), Throws.InstanceOf<Exception>().And.Message.StartsWith($"InMemorySagaPersister concurrency violation: saga entity Id[{saga.Id}] already saved.")); losingSessionContext = new ContextBag(); var returnedSaga3 = await Task.Run(() => persister.Get<TestSagaData>("SomeId", sagaId.ToString(), new InMemorySynchronizedStorageSession(), losingSessionContext)); winningSessionContext = new ContextBag(); var returnedSaga4 = await persister.Get<TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), winningSessionContext); winningSaveSession = new InMemorySynchronizedStorageSession(); losingSaveSession = new InMemorySynchronizedStorageSession(); await persister.Update(returnedSaga4, winningSaveSession, winningSessionContext); await persister.Update(returnedSaga3, losingSaveSession, losingSessionContext); await winningSaveSession.CompleteAsync(); Assert.That(async () => await losingSaveSession.CompleteAsync(), Throws.InstanceOf<Exception>().And.Message.StartsWith($"InMemorySagaPersister concurrency violation: saga entity Id[{saga.Id}] already saved.")); }
public async Task Save_fails_when_writing_same_data_twice() { var saga = new TestSagaData { Id = Guid.NewGuid() }; var persister = new InMemorySagaPersister(); var insertSession = new InMemorySynchronizedStorageSession(); await persister.Save(saga, SagaMetadataHelper.GetMetadata<TestSaga>(saga), insertSession, new ContextBag()); await insertSession.CompleteAsync(); var retrievingContext = new ContextBag(); var returnedSaga1 = await persister.Get<TestSagaData>(saga.Id, new InMemorySynchronizedStorageSession(), retrievingContext); var winningSaveSession = new InMemorySynchronizedStorageSession(); var losingSaveSession = new InMemorySynchronizedStorageSession(); await persister.Update(returnedSaga1, winningSaveSession, retrievingContext); await persister.Update(returnedSaga1, losingSaveSession, retrievingContext); await winningSaveSession.CompleteAsync(); Assert.That(async () => await losingSaveSession.CompleteAsync(), Throws.InstanceOf<Exception>().And.Message.StartsWith($"InMemorySagaPersister concurrency violation: saga entity Id[{saga.Id}] already saved.")); }