static async Task <TransportOperation[]> InvokeMessageHandler(IExtendable context, Func <Task> next) { var pendingOperations = new PendingTransportOperations(); context.Extensions.Set(pendingOperations); await next(); return(pendingOperations.Operations); }
async Task CaptureMessages(Func <IMessageSession, Task> operation, ExtendableOptions options) { var pendingOperations = new PendingTransportOperations(); options.GetExtensions().Set(pendingOperations); await operation(rootSession).ConfigureAwait(false); var messageRecords = pendingOperations.Operations.Select(o => o.ToMessageRecord(requestId, TransactionContext.AttemptId)).Cast <SideEffectRecord>().ToList(); var messagesToCheck = pendingOperations.Operations.Select(o => o.ToCheck()).ToArray(); await TransactionContext.AddSideEffects(messageRecords).ConfigureAwait(false); await messageStore.Create(messagesToCheck).ConfigureAwait(false); }
public static Task Process <T>(this ISagaManager sagaManager, string correlationId, IMessageHandlerContext context, Func <T, Task <T> > handlerCallback) where T : class, new() { return(sagaManager.Process(context.MessageId, correlationId, context.Extensions, (Func <T, ContextBag, Task <(T, PendingTransportOperations)> >)(async(sagaData, bag) => { var pendingTransportOperations = new PendingTransportOperations(); bag.Set(pendingTransportOperations); //override the one set by the outbox var newSagaData = await handlerCallback(sagaData).ConfigureAwait(false); bag.Remove <PendingTransportOperations>(); //Restore old value return (newSagaData, pendingTransportOperations); }))); }
public async Task Should_clear_added_pending_operations_and_restore_ones_from_outbox_record() { var messageId = Guid.NewGuid().ToString(); var transportOperations = new[] { new TransportOperation( messageId: "42", properties: new DispatchProperties { { "Destination", "somewhere" } }, body: Array.Empty <byte>(), headers: new Dictionary <string, string>()), }; var fakeCosmosClient = new FakeCosmosClient(new FakeContainer { ReadItemStreamOutboxRecord = (id, key) => new OutboxRecord { Dispatched = false, Id = messageId, TransportOperations = transportOperations.Select(op => new StorageTransportOperation(op)) .ToArray() } }); var containerHolderHolderResolver = new ContainerHolderResolver(new FakeProvider(fakeCosmosClient), new ContainerInformation("fakeContainer", new PartitionKeyPath("")), "fakeDatabase"); var behavior = new OutboxBehavior(containerHolderHolderResolver, new JsonSerializer()); var testableContext = new TestableIncomingLogicalMessageContext(); testableContext.Extensions.Set(new PartitionKey("")); testableContext.Extensions.Set(new SetAsDispatchedHolder()); testableContext.Extensions.Set <IOutboxTransaction>(new CosmosOutboxTransaction(containerHolderHolderResolver, testableContext.Extensions)); var pendingTransportOperations = new PendingTransportOperations(); pendingTransportOperations.Add(new Transport.TransportOperation(new OutgoingMessage(null, null, null), null)); testableContext.Extensions.Set(pendingTransportOperations); await behavior.Invoke(testableContext, c => Task.CompletedTask); Assert.IsTrue(pendingTransportOperations.HasOperations, "Should have exactly one operation added found on the outbox record"); Assert.AreEqual("42", pendingTransportOperations.Operations.ElementAt(0).Message.MessageId, "Should have exactly one operation added found on the outbox record"); }
public override async Task Invoke(IIncomingLogicalMessageContext context, Func <Task> next) { var transaction = context.Extensions.Get <ITransactionContext>(); var pendingOperations = new PendingTransportOperations(); context.Extensions.Set(pendingOperations); await next().ConfigureAwait(false); var messageRecords = pendingOperations.Operations.Select(o => o.ToMessageRecord(context.MessageId, transaction.AttemptId)).Cast <SideEffectRecord>().ToList(); var messagesToCheck = pendingOperations.Operations.Select(o => o.ToCheck()).ToArray(); await transaction.AddSideEffects(messageRecords).ConfigureAwait(false); await messageStore.Create(messagesToCheck).ConfigureAwait(false); }