Skip to content

Push the cancellation token through the retry stores - #5732

Merged
johnsimons merged 1 commit into
masterfrom
john/cancel_part4
Aug 11, 2026
Merged

johnsimons merged 1 commit into
masterfrom
john/cancel_part4

Conversation

@johnsimons

Copy link
Copy Markdown
Member

Push the cancellation token through the retry stores

Fourth slice of the cancellation propagation work, and the second Phase 3 slice. Covers the retry interface group: IRetryBatchStore (10 methods), IRetryStagingStore (10) and IRetryHistoryDataStore (3), both persisters, 17 host call sites.

Deletes a debt block

ServiceControl/.editorconfig no longer carries the Recoverability/Retrying/RetriesGateway.cs block. This is the first project-level suppression the burn-down has removed outright rather than narrowed, and it was one of the three the plan named as the signal that Phase 3 is landing. Both conditions its comment was waiting on are now met:

  • PS0013. BulkRetryRequest.Invoke forwarded a Func<string, DateTime, Task> straight into ForEachUnresolvedMessage and friends. That callback is now Func<string, DateTime, CancellationToken, Task>, so the store hands each streamed message the token it is iterating under. All four overrides follow.
  • PS0004. The comment said the private AssignMessagesToBatch could not take a required token "until the parameters are reordered". Done: the token moved from last position to position 5, ahead of the trailing optionals, because C# forbids a required parameter after optional ones (CS1737). CA1068 explicitly permits optional parameters after a required token, so the result is legal and rule-clean. Three call sites updated.

The error instance is now down to 4 cancellation diagnostics from 7, and all four are the transport and external-integration files that later phases own.

Progress

Project Before After
ServiceControl.Persistence.EFCore 156 118
ServiceControl.Persistence.RavenDB 146 119
ServiceControl.Persistence 94 67
ServiceControl.Persistence.Tests 167 167

92 diagnostics retired, 563 to 471 across the four persistence projects.

Persistence.Tests does not move. Its 10 remaining retry hits are PS0018 on test-local helper methods, which belong to the blanket test-project escape rather than to this slice.

Worth a reviewer's attention

  • One existing CancellationToken.None is deliberately left in place. RetryBatchStore.AssignMessagesToBatch now has a token, so it could be forwarded to dialect.InsertMissingRetryClaims, but that call is an established explicit opt-out sitting inside a transaction the dialect owns, and flipping it changes runtime behaviour on a write path. Called out here rather than changed silently. It also carries no comment explaining the opt-out, which the convention asks for and which would be worth adding either way.
  • Three failure-bookkeeping writes in RetryProcessor now take the token: RecordStagingFailure, IncrementStagingAttempts and RemoveFromBatch. Each sits in a catch (Exception e) preceded by a catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) filter, so the token is guaranteed live on entry. If shutdown does land mid-write, the batch is left for AdoptOrphanedBatches to re-adopt on restart, which is the existing recovery path.
  • InTransaction in the EFCore staging store changes from Func<Task> to Func<CancellationToken, Task> with a required token, satisfying both PS0013 and PS0004. Its three lambdas become async token =>. It is private and self-contained, unlike DataStoreBase.ExecuteWithDbContext, which remains deliberately unconverted until the last store lands.

@johnsimons
johnsimons requested a review from rbev August 11, 2026 04:24
@johnsimons johnsimons self-assigned this Aug 11, 2026
@johnsimons
johnsimons marked this pull request as ready for review August 11, 2026 04:48
Base automatically changed from john/cancel_part3 to master August 11, 2026 10:37
…ementations

This change continues the effort to consistently apply optional `CancellationToken` parameters to asynchronous methods within the persistence data store interfaces (`IRetryBatchStore`, `IRetryHistoryDataStore`, `IRetryStagingStore`) and their EFCore and RavenDB implementations.

The cancellation tokens are now propagated to underlying asynchronous database calls and to consuming services. This ensures proper cancellation of long-running database operations and resolves related static analysis warnings, further reducing cancellation analyzer debt.
@johnsimons
johnsimons merged commit fa72695 into master Aug 11, 2026
50 checks passed
@johnsimons
johnsimons deleted the john/cancel_part4 branch August 11, 2026 11:55
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