async Task Dispatch(CapturedTransportOperation operation, RootContext rootContext) { using (var conn = settings.Links[operation.Destination].ConnectionFactory()) { await conn.OpenAsync().ConfigureAwait(false); using (var trans = conn.BeginTransaction()) { //Will block until the record insert transaction is completed. await OutboxPersister.MarkAsDispatched(operation, conn, trans).ConfigureAwait(false); var iface = settings.GetDestinationInterface(operation.Destination); var chains = rootContext.Interfaces.GetChainsFor(iface); var chain = chains.Get <AnycastContext>(); var dispatchContext = new OutboxDispatchContext(rootContext, iface); var forwardContext = new AnycastContext(operation.Destination, operation.OutgoingMessage, DistributionStrategyScope.Send, dispatchContext); dispatchContext.Set(new TransportTransaction()); await chain.Invoke(forwardContext).ConfigureAwait(false); //Only commit the transaction if the dispatch succeeded. trans.Commit(); } } }
protected override async Task <bool> Terminate(ForwardReplyContext context) { string replyTo = null; string replyToRouter = null; if (!context.ReceivedHeaders.TryGetValue(Headers.CorrelationId, out var correlationId)) { throw new UnforwardableMessageException($"The reply has to contain a '{Headers.CorrelationId}' header set by the router connector when sending out the initial message."); } try { correlationId.DecodeTLV((t, v) => { if (t == "reply-to") { replyTo = v; } if (t == "id") { context.ForwardedHeaders[Headers.CorrelationId] = v; } if (t == "reply-to-router") { replyToRouter = v; } }); } catch (Exception e) { throw new UnforwardableMessageException($"Cannot decode value in '{Headers.CorrelationId}' header: " + e.Message); } var outgoingMessage = new OutgoingMessage(context.MessageId, context.ForwardedHeaders, context.ReceivedBody); if (replyTo != null) { var operation = new TransportOperation(outgoingMessage, new UnicastAddressTag(replyTo)); var chain = context.Chains.Get <PostroutingContext>(); var forkContext = new PostroutingContext(null, operation, context); await chain.Invoke(forkContext).ConfigureAwait(false); return(true); } if (replyToRouter != null) { var chain = context.Chains.Get <AnycastContext>(); var forkContext = new AnycastContext(replyToRouter, outgoingMessage, DistributionStrategyScope.Send, context); await chain.Invoke(forkContext).ConfigureAwait(false); return(true); } throw new UnforwardableMessageException("The reply contains neither \'reply-to\' nor \'reply-to-router\' correlation parameters required to route the message."); }
public async Task Start(RootContext rootContext, SettingsHolder extensibilitySettings) { tokenSource = new CancellationTokenSource(); foreach (var persister in persisters) { async Task Dispatch(OutgoingMessage operation) { var destinationEndpoint = persister.Key; var iface = destinationToInterfaceMap[destinationEndpoint]; var chains = rootContext.Interfaces.GetChainsFor(iface); var chain = chains.Get <AnycastContext>(); var dispatchContext = new OutboxDispatchContext(rootContext, iface); var forwardContext = new AnycastContext(destinationEndpoint, operation, DistributionStrategyScope.Send, dispatchContext); dispatchContext.Set(new TransportTransaction()); await chain.Invoke(forwardContext).ConfigureAwait(false); } await persister.Value.Start(tokenSource.Token, Dispatch); } }