Skip to content

Continue cancellation token propagation in persistence layer - #5731

Merged
johnsimons merged 1 commit into
john/cancel_part2from
john/cancel_part3
Aug 11, 2026
Merged

johnsimons merged 1 commit into
john/cancel_part2from
john/cancel_part3

Conversation

@johnsimons

Copy link
Copy Markdown
Member

Covers two interface groups together, because ErrorMessagesDataStore implements all four of their interfaces and is better converted in one pass than left half-done:

  • Query stores: IFailedMessageQueryDataStore (7), IMessagesViewDataStore (5), IQueueAddressStore (1)
  • Lifecycle and retry: IFailedMessageLifecycleDataStore (5), IFailedMessageRetryDataStore (5)

23 interface methods, both persisters, 15 host call sites, 3 test doubles. The highest actual payoff is ServiceControl/CompositeViews, the scatter-gather HTTP fan-out to remote instances, where an abandoned request previously kept running to completion against every remote.

Two things worth a reviewer's attention:

  • ProcessPendingRetries' callback became Func<string, CancellationToken, Task> (PS0013). The store owns the streaming loop, so it hands each iteration its own token. At the one real caller, MessageFailureResolvedHandler, that token is genuinely unused: NServiceBus' IPipelineContext.Send overloads deliberately take no CancellationToken (the token lives on the context). It is left unused rather than given an invented use.
  • A stale workaround is deleted in ReturnToSenderDequeuer.CaptureIfMessageSendingFails.OnError. It carried _ = cancellationToken; under a comment claiming the token could not be propagated "since it would require to change the data store APIs". The comment was already wrong, since the token was in use two lines below at domainEvents.Raise and in the catch filter. RevertRetry was the last real gap and this closes it.

DataStoreBase.ExecuteWithDbContext is deliberately left alone: the lambdas now close over the enclosing cancellationToken, so propagation is complete and correct with no blast radius. Changing its Func to carry the token would break lambda arity at roughly 40 stores and force CancellationToken.None placeholders in the ones not yet converted. Done last instead, it is a mechanical sweep over already-tokenised code.

@johnsimons johnsimons self-assigned this Aug 11, 2026
@johnsimons
johnsimons requested a review from rbev August 11, 2026 04:12
@johnsimons
johnsimons marked this pull request as ready for review August 11, 2026 04:12
Expands the application of optional `CancellationToken` parameters to asynchronous methods across all persistence data store interfaces and their EFCore and RavenDB implementations. This allows for more granular control over cancelling long-running database operations and further addresses cancellation-related static analysis warnings.
@johnsimons
johnsimons merged commit 9056a49 into master Aug 11, 2026
99 checks passed
@johnsimons
johnsimons deleted the john/cancel_part3 branch August 11, 2026 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants