コード例 #1
0
    async Task <OutboxMessage> StoreDispatchAndGetAsync()
    {
        var operations = new List <TransportOperation>
        {
            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";

        using (var connection = await dbConnection.OpenConnection().ConfigureAwait(false))
            using (var transaction = connection.BeginTransaction())
            {
                await persister.Store(new OutboxMessage(messageId, operations.ToArray()), transaction, connection).ConfigureAwait(false);

                transaction.Commit();
            }
        await persister.SetAsDispatched(messageId, null).ConfigureAwait(false);

        return(await persister.Get(messageId, null).ConfigureAwait(false));
    }
コード例 #2
0
    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);
    }
コード例 #3
0
        public void Should_delete_all_OutboxRecords_that_have_been_dispatched()
        {
            var id = Guid.NewGuid().ToString("N");

            var sessionFactory = new RavenSessionFactory(store);

            var persister = new OutboxPersister(sessionFactory) { DocumentStore = store, EndpointName = "TestEndpoint" };
            persister.Store("NotDispatched", Enumerable.Empty<TransportOperation>());
            persister.Store(id, new List<TransportOperation>
            {
                new TransportOperation(id, new Dictionary<string, string>(), new byte[1024*5], new Dictionary<string, string>()),
            });

            sessionFactory.SaveChanges();
            sessionFactory.ReleaseSession();

            persister.SetAsDispatched(id);
            Thread.Sleep(TimeSpan.FromSeconds(1)); //Need to wait for dispatch logic to finish

            WaitForIndexing(store);

            var cleaner = new OutboxRecordsCleaner { DocumentStore = store };
            cleaner.RemoveEntriesOlderThan(DateTime.UtcNow.AddMinutes(1));

            using (var session = store.OpenSession())
            {
                var result = session.Query<OutboxRecord>().ToList();

                Assert.AreEqual(1, result.Count);
                Assert.AreEqual("NotDispatched", result[0].MessageId);
            }
        }
コード例 #4
0
    async Task Store(int i, DbConnection connection, OutboxPersister persister)
    {
        var operations = new[]
        {
            new TransportOperation(
                messageId: "OperationId" + i,
                options: new Dictionary <string, string>
            {
                {
                    "OptionKey1", "OptionValue1"
                }
            },
                body: new byte[]
            {
                0x20
            },
                headers: new Dictionary <string, string>
            {
                {
                    "HeaderKey1", "HeaderValue1"
                }
            }
                )
        };
        var messageId     = "MessageId" + i;
        var outboxMessage = new OutboxMessage(messageId, operations);

        using (var transaction = connection.BeginTransaction())
        {
            await persister.Store(outboxMessage, transaction, connection).ConfigureAwait(false);

            transaction.Commit();
        }
        await persister.SetAsDispatched(messageId, null).ConfigureAwait(false);
    }
コード例 #5
0
        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);
            }
        }
コード例 #6
0
        public async Task Should_store_expiry_in_metadata_if_time_to_keep_deduplication_data_is_finite()
        {
            // arrange
            var timeToKeepDeduplicationData = TimeSpan.FromSeconds(60);
            var persister         = new OutboxPersister("TestEndpoint", CreateTestSessionOpener(), timeToKeepDeduplicationData);
            var context           = new ContextBag();
            var incomingMessageId = SimulateIncomingMessage(context).MessageId;
            var outboxRecordId    = "Outbox/TestEndpoint/" + incomingMessageId;

            //manually store an OutboxRecord to control the OutboxRecordId format
            using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency())
            {
                await session.StoreAsync(new OutboxRecord { MessageId = incomingMessageId, Dispatched = false, }, outboxRecordId);

                await session.SaveChangesAsync();
            }

            var expectedExpiry           = DateTime.UtcNow.Add(timeToKeepDeduplicationData);
            var maxExpectedExecutionTime = TimeSpan.FromMinutes(15);

            // act
            await persister.SetAsDispatched(incomingMessageId, context);

            // assert
            using (var session = store.OpenAsyncSession().UsingOptimisticConcurrency())
            {
                var outboxRecord = await session.LoadAsync <OutboxRecord>(outboxRecordId);

                var metadata = session.Advanced.GetMetadataFor(outboxRecord);
                var expiry   = DateTime.Parse((string)metadata[Constants.Documents.Metadata.Expires], default, DateTimeStyles.RoundtripKind);
コード例 #7
0
        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);
            }
        }
コード例 #8
0
        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");

            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(store);

            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);
            }
        }
コード例 #9
0
        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);
            }
        }
コード例 #10
0
    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));
    }
コード例 #11
0
        public async Task Should_set_messages_as_dispatched_with_old_and_new_recordId_format(string outboxRecordIdPrefix)
        {
            var persister = new OutboxPersister(store, testEndpointName);

            var messageId = Guid.NewGuid().ToString();

            //manually store an OutboxRecord to control the OutboxRecordId format
            using (var session = OpenSession())
            {
                session.Store(new OutboxRecord
                {
                    Id                  = outboxRecordIdPrefix + messageId,
                    MessageId           = messageId,
                    Dispatched          = false,
                    TransportOperations = new[]
                    {
                        new OutboxRecord.OutboxOperation
                        {
                            Message   = new byte[1024 * 5],
                            Headers   = new Dictionary <string, string>(),
                            MessageId = messageId,
                            Options   = new Dictionary <string, string>()
                        }
                    }
                });

                await session.SaveChangesAsync();
            }

            await persister.SetAsDispatched(messageId, new ContextBag());

            using (var session = OpenSession())
            {
                var result = await session.LoadAsync <OutboxRecord>(outboxRecordIdPrefix + messageId);

                Assert.NotNull(result);
                Assert.True(result.Dispatched);
            }
        }
コード例 #12
0
    async Task <Tuple <OutboxMessage, OutboxMessage> > StoreDispatchAndGetAsync(OutboxPersister persister)
    {
        var operations = new List <TransportOperation>
        {
            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";

        using (var connection = await connectionManager.OpenNonContextualConnection().ConfigureAwait(false))
            using (var transaction = connection.BeginTransaction())
            {
                await persister.Store(new OutboxMessage(messageId, operations.ToArray()), transaction, connection).ConfigureAwait(false);

                transaction.Commit();
            }
        var beforeDispatch = await persister.Get(messageId, null).ConfigureAwait(false);

        await persister.SetAsDispatched(messageId, null).ConfigureAwait(false);

        var afterDispatch = await persister.Get(messageId, null).ConfigureAwait(false);

        return(Tuple.Create(beforeDispatch, afterDispatch));
    }
コード例 #13
0
        public void Should_update_dispatched_flag()
        {
            var id = Guid.NewGuid().ToString("N");

            var sessionFactory = new RavenSessionFactory(store);
            var persister = new OutboxPersister(sessionFactory) { DocumentStore = store, EndpointName = "TestEndpoint" };
            persister.Store(id, new List<TransportOperation>
            {
                new TransportOperation(id, new Dictionary<string, string>(), new byte[1024*5], new Dictionary<string, string>()),
            });

            sessionFactory.SaveChanges();
            sessionFactory.ReleaseSession();

            persister.SetAsDispatched(id);

            WaitForIndexing(store);

            using (var session = store.OpenSession())
            {
                var result = session.Query<OutboxRecord>().Where(o => o.MessageId == id)
                    .SingleOrDefault();

                Assert.NotNull(result);
                Assert.True(result.Dispatched);
            }
        }
コード例 #14
0
        public void Should_set_messages_as_dispatched_with_old_and_new_recordId_format(string outboxRecordIdPrefix)
        {
            var sessionFactory = new RavenSessionFactory(store);
            var persister = new OutboxPersister(sessionFactory) { DocumentStore = store, EndpointName = "TestEndpoint" };

            var messageId = Guid.NewGuid().ToString();

            //manually store an OutboxRecord to control the OutboxRecordId format
            sessionFactory.Session.Store(new OutboxRecord
            {
                MessageId = messageId,
                Dispatched = false,
                TransportOperations = new List<OutboxRecord.OutboxOperation>
                {
                    new OutboxRecord.OutboxOperation
                    {
                        Message = new byte[1024 * 5],
                        Headers = new Dictionary<string, string>(),
                        MessageId = messageId,
                        Options = new Dictionary<string, string>()
                    }
                }
            }, outboxRecordIdPrefix + messageId);

            sessionFactory.SaveChanges();
            sessionFactory.ReleaseSession();

            persister.SetAsDispatched(messageId);
            sessionFactory.ReleaseSession();

            var result = sessionFactory.Session.Load<OutboxRecord>(outboxRecordIdPrefix + messageId);

            Assert.NotNull(result);
            Assert.True(result.Dispatched);
        }
コード例 #15
0
        public async Task Should_update_dispatched_flag()
        {
            var persister = new OutboxPersister(store, testEndpointName);

            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(store);

            using (var s = store.OpenAsyncSession())
            {
                var result = await s.Query<OutboxRecord>()
                    .SingleOrDefaultAsync(o => o.MessageId == id);

                Assert.NotNull(result);
                Assert.True(result.Dispatched);
            }
        }
コード例 #16
0
        public async Task Should_set_messages_as_dispatched_with_old_and_new_recordId_format(string outboxRecordIdPrefix)
        {
            var persister = new OutboxPersister(store, testEndpointName);

            var messageId = Guid.NewGuid().ToString();

            //manually store an OutboxRecord to control the OutboxRecordId format
            using (var session = OpenAsyncSession())
            {
                await session.StoreAsync(new OutboxRecord
                {
                    MessageId = messageId,
                    Dispatched = false,
                    TransportOperations = new []
                    {
                        new OutboxRecord.OutboxOperation
                        {
                            Message = new byte[1024*5],
                            Headers = new Dictionary<string, string>(),
                            MessageId = messageId,
                            Options = new Dictionary<string, string>()
                        }
                    }
                }, outboxRecordIdPrefix + messageId);

                await session.SaveChangesAsync();
            }

            await persister.SetAsDispatched(messageId, new ContextBag());

            using (var session = OpenAsyncSession())
            {
                var result = await session.LoadAsync<OutboxRecord>(outboxRecordIdPrefix + messageId);

                Assert.NotNull(result);
                Assert.True(result.Dispatched);
            }
            
        }