public async Task When_a_duplicate_messages_starting_a_saga_arrive_simultanously_one_of_them_fails() { var context = CreateMessageContext(); var transaction1 = await outboxPersister.BeginTransaction(context); var session1 = new OutboxEventStoreSynchronizedStorageSession(connection, (EventStoreOutboxTransaction)transaction1); var sagaData = CreateNewSagaData(); await persister.Save(sagaData, new SagaCorrelationProperty(CorrelationPropName, sagaData.StringProperty), session1, context); var transaction2 = await outboxPersister.BeginTransaction(context); var session2 = new OutboxEventStoreSynchronizedStorageSession(connection, (EventStoreOutboxTransaction)transaction2); try { await persister.Save(sagaData, new SagaCorrelationProperty(CorrelationPropName, sagaData.StringProperty), session2, context); Assert.Fail("Expected exception"); } catch (Exception ex) { StringAssert.StartsWith("Append failed due to WrongExpectedVersion.", ex.Message); } }
static async Task Store(int i, OutboxPersister persister, CancellationToken cancellationToken = default) { var operations = new[] { new TransportOperation( messageId: "OperationId" + i, properties: new DispatchProperties(new Dictionary <string, string> { { "OptionKey1", "OptionValue1" } }), body: new byte[] { 0x20 }, headers: new Dictionary <string, string> { { "HeaderKey1", "HeaderValue1" } } ) }; var messageId = "MessageId" + i; var contextBag = CreateContextBag(messageId); using (var transaction = await persister.BeginTransaction(contextBag, cancellationToken)) { await persister.Store(new OutboxMessage(messageId, operations), transaction, contextBag, cancellationToken).ConfigureAwait(false); await transaction.Commit(cancellationToken); } await persister.SetAsDispatched(messageId, contextBag, cancellationToken).ConfigureAwait(false); }
public async Task Should_update_dispatched_flag() { var persister = new OutboxPersister(store, testEndpointName, CreateTestSessionOpener()); var id = Guid.NewGuid().ToString("N"); var message = new OutboxMessage(id, new [] { new TransportOperation(id, new Dictionary <string, string>(), new byte[1024 * 5], new Dictionary <string, string>()) }); using (var transaction = await persister.BeginTransaction(new ContextBag())) { await persister.Store(message, transaction, new ContextBag()); await transaction.Commit(); } await persister.SetAsDispatched(id, new ContextBag()); WaitForIndexing(); using (var s = store.OpenAsyncSession()) { var result = await s.Query <OutboxRecord>() .SingleOrDefaultAsync(o => o.MessageId == id); Assert.NotNull(result); Assert.True(result.Dispatched); } }
async Task <OutboxMessage> StoreAndGetAsync(OutboxPersister persister) { var operations = new[] { new TransportOperation( messageId: "Id1", options: new Dictionary <string, string> { { "OptionKey1", "OptionValue1" } }, body: new byte[] { 0x20, 0x21 }, headers: new Dictionary <string, string> { { "HeaderKey1", "HeaderValue1" } } ) }; var messageId = "a"; var contextBag = CreateContextBag(messageId); using (var transaction = await persister.BeginTransaction(contextBag)) { await persister.Store(new OutboxMessage(messageId, operations), transaction, contextBag).ConfigureAwait(false); await transaction.Commit(); } return(await persister.Get(messageId, contextBag).ConfigureAwait(false)); }
public async Task Should_delete_all_OutboxRecords_that_have_been_dispatched() { var id = Guid.NewGuid().ToString("N"); var context = new ContextBag(); var persister = new OutboxPersister(store, "TestEndpoint", CreateTestSessionOpener()); using (var transaction = await persister.BeginTransaction(context)) { await persister.Store(new OutboxMessage("NotDispatched", new TransportOperation[0]), transaction, context); await transaction.Commit(); } var outboxMessage = new OutboxMessage(id, new [] { new TransportOperation(id, new Dictionary <string, string>(), new byte[1024 * 5], new Dictionary <string, string>()) }); using (var transaction = await persister.BeginTransaction(context)) { await persister.Store(outboxMessage, transaction, context); await transaction.Commit(); } await persister.SetAsDispatched(id, context); await Task.Delay(TimeSpan.FromSeconds(1)); //Need to wait for dispatch logic to finish //WaitForUserToContinueTheTest(store); WaitForIndexing(); var cleaner = new OutboxRecordsCleaner(store); await cleaner.RemoveEntriesOlderThan(DateTime.UtcNow.AddMinutes(1)); using (var s = store.OpenAsyncSession()) { var result = await s.Query <OutboxRecord>().ToListAsync(); Assert.AreEqual(1, result.Count); Assert.AreEqual("NotDispatched", result[0].MessageId); } }
public async Task Should_throw_if__trying_to_insert_same_messageid() { var persister = new OutboxPersister(store, testEndpointName, CreateTestSessionOpener()); using (var transaction = await persister.BeginTransaction(new ContextBag())) { await persister.Store(new OutboxMessage("MySpecialId", new TransportOperation[0]), transaction, new ContextBag()); await transaction.Commit(); } var exception = await Catch <ConcurrencyException>(async() => { using (var transaction = await persister.BeginTransaction(new ContextBag())) { await persister.Store(new OutboxMessage("MySpecialId", new TransportOperation[0]), transaction, new ContextBag()); await transaction.Commit(); } }); Assert.NotNull(exception); }
public async Task Should_be_deleted() { await store.Maintenance.SendAsync( new ConfigureExpirationOperation( new ExpirationConfiguration { Disabled = false, DeleteFrequencyInSec = 1, })); // arrange var persister = new OutboxPersister("TestEndpoint", CreateTestSessionOpener(), TimeSpan.FromSeconds(1)); var context = new ContextBag(); var incomingMessageId = SimulateIncomingMessage(context).MessageId; var dispatchedOutboxMessage = new OutboxMessage(incomingMessageId, new TransportOperation[0]); var notDispatchedOutboxMessage = new OutboxMessage("NotDispatched", new TransportOperation[0]); using (var transaction = await persister.BeginTransaction(context)) { await persister.Store(dispatchedOutboxMessage, transaction, context); await persister.Store(notDispatchedOutboxMessage, transaction, context); await transaction.Commit(); } await persister.SetAsDispatched(dispatchedOutboxMessage.MessageId, context); // act // wait for dispatch logic and expiry to finish, not ideal but polling on BASE index is also not great await Task.Delay(TimeSpan.FromSeconds(3)); WaitForIndexing(); // assert using (var session = store.OpenAsyncSession()) { var outboxRecords = await session.Query <OutboxRecord>().ToListAsync(); Assert.AreEqual(1, outboxRecords.Count); Assert.AreEqual(notDispatchedOutboxMessage.MessageId, outboxRecords.Single().MessageId); } }
static async Task <Tuple <OutboxMessage, OutboxMessage> > StoreDispatchAndGetAsync(OutboxPersister persister, CancellationToken cancellationToken = default) { var operations = new List <TransportOperation> { new TransportOperation( messageId: "Id1", properties: new DispatchProperties(new Dictionary <string, string> { { "OptionKey1", "OptionValue1" } }), body: new byte[] { 0x20, 0x21 }, headers: new Dictionary <string, string> { { "HeaderKey1", "HeaderValue1" } } ) }; var messageId = "a"; var contextBag = CreateContextBag(messageId); using (var transaction = await persister.BeginTransaction(contextBag, cancellationToken)) { await persister.Store(new OutboxMessage(messageId, operations.ToArray()), transaction, contextBag, cancellationToken).ConfigureAwait(false); await transaction.Commit(cancellationToken); } var beforeDispatch = await persister.Get(messageId, contextBag, cancellationToken).ConfigureAwait(false); await persister.SetAsDispatched(messageId, contextBag, cancellationToken).ConfigureAwait(false); var afterDispatch = await persister.Get(messageId, contextBag, cancellationToken).ConfigureAwait(false); return(Tuple.Create(beforeDispatch, afterDispatch)); }
public async Task Should_save_with_not_dispatched() { var persister = new OutboxPersister(store, testEndpointName, CreateTestSessionOpener()); var id = Guid.NewGuid().ToString("N"); var message = new OutboxMessage(id, new[] { new TransportOperation(id, new Dictionary <string, string>(), new byte[1024 * 5], new Dictionary <string, string>()) }); using (var transaction = await persister.BeginTransaction(new ContextBag())) { await persister.Store(message, transaction, new ContextBag()); await transaction.Commit(); } var result = await persister.Get(id, new ContextBag()); var operation = result.TransportOperations.Single(); Assert.AreEqual(id, operation.MessageId); }
public async Task Should_filter_invalid_docid_character() { var persister = new OutboxPersister(store, testEndpointName, CreateTestSessionOpener()); var guid = Guid.NewGuid(); var messageId = $@"{guid}\12345"; var emptyDictionary = new Dictionary <string, string>(); var operation = new TransportOperation("test", emptyDictionary, new byte[0], emptyDictionary); var transportOperations = new [] { operation }; using (var transaction = await persister.BeginTransaction(new ContextBag())) { await persister.Store(new OutboxMessage(messageId, transportOperations), transaction, new ContextBag()); await transaction.Commit(); } var outboxMessage = await persister.Get(messageId, new ContextBag()); Assert.AreEqual(messageId, outboxMessage.MessageId); Assert.AreEqual(1, outboxMessage.TransportOperations.Length); Assert.AreEqual("test", outboxMessage.TransportOperations[0].MessageId); }