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(); } } }
public async Task Store(CapturedTransportOperation operation, Action triggerAdvance, SqlConnection conn, SqlTransaction trans) { var localState = linkState; var seq = await sequence.GetNextValue(conn, trans).ConfigureAwait(false); InterlocedEx.ExchangeIfGreaterThan(ref highestSeq, seq); if (localState.IsStale(seq)) { var freshLinkState = await linkStateTable.Get(operation.Destination, conn, trans).ConfigureAwait(false); UpdateCachedLinkState(freshLinkState); localState = linkState; } if (localState.ShouldAdvance(seq)) { triggerAdvance(); } if (localState.IsStale(seq)) { throw new ProcessCurrentMessageLaterException("Link state is stale. Processing current message later."); } var tableName = localState.GetTableName(seq); var table = new OutboxTable(tableName); try { operation.OutgoingMessage.Headers[RouterDeduplicationHeaders.SequenceNumber] = seq.ToString(); operation.OutgoingMessage.Headers[RouterDeduplicationHeaders.SequenceKey] = sourceKey; operation.AssignTable(tableName); operation.AssignSequence(seq); var persistentOperation = Convert(operation); await table.Insert(persistentOperation, seq, conn, trans).ConfigureAwait(false); } catch (SqlException e) { if (e.Number == 547) //Constraint violation. We used very old seq and that value cannot be used any more because the epoch has advanced. { var freshLinkState = await linkStateTable.Get(operation.Destination, conn, trans).ConfigureAwait(false); UpdateCachedLinkState(freshLinkState); throw new ProcessCurrentMessageLaterException("Link state is stale. Processing current message later."); } throw; } catch (Exception ex) { log.Debug($"Unhandled exception while storing outbox operation with sequence {seq}", ex); throw; } }
public Task Store(CapturedTransportOperation operation, SqlConnection conn, SqlTransaction trans) { return(persisters[operation.Destination].Store(operation, conn, trans)); }
public void Enqueue(CapturedTransportOperation operation) { operationsQueue.Add(operation); }
public Task Store(CapturedTransportOperation operation, SqlConnection conn, SqlTransaction trans) { return(persister.Store(operation, () => @event.Set(), conn, trans)); }