Skip to content

feat(batching): ProbeIndividuallyAfter(N) count-based batch member isolation (GH-3289 Phase 3c)#3312

Merged
jeremydmiller merged 1 commit into
mainfrom
feat-batching-phase3c-probe-after-3289
Jul 5, 2026
Merged

feat(batching): ProbeIndividuallyAfter(N) count-based batch member isolation (GH-3289 Phase 3c)#3312
jeremydmiller merged 1 commit into
mainfrom
feat-batching-phase3c-probe-after-3289

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Phase 3c of the #3289 batch-processing plan: item 2 (ProbeIndividuallyAfter), the count-based sibling of item 3's IsolateBatchMembers (#3311). (Phases 0/1/2/3a/3b all merged.)

The feature

When you don't have a specific exception type to key on — the batch just fails and you can't tell transient from poison — configure a count-based probe directly on the batch:

opts.BatchMessagesOf<Order>(b =>
{
    b.BatchSize = 500;
    b.ProbeIndividuallyAfter(attempts: 3); // retry the whole batch 3×, THEN probe each member
});

It retries the whole batch N times (so a transient failure clears on retry), and only then re-runs each member as its own size-1 batch so only the genuinely bad one dead-letters.

Implementation

  • ProbeIndividuallyContinuation gains a probeAfterAttempts threshold: it requeues the whole batch (DeferAsync) while Envelope.Attempts < threshold, then probes into singletons. The size-≤1 guard still dead-letters immediately (terminating case + probed singletons). IsolateBatchMembers keeps threshold 1 (probe on first failure) — behavior unchanged, verified by re-running its tests.
  • BatchingOptions.ProbeIndividuallyAfter(N) stores the threshold; a new startup step applyBatchProbePolicies() (next to the existing warnOrAssertBatchHandlerConflicts) installs it as an every-attempt failure rule on the batch handler chain via batchChain.OnException<Exception>().ContinueWith(new ProbeIndividuallyContinuationSource(N)).

Test (DB-free)

batch_probe_individually_after.cs: the whole 3-item batch is retried exactly 3 times (asserted), then the probe isolates the poison item — the two healthy members succeed as singletons and only bad is dead-lettered (captured via IDeadLetterInterceptor). Item 3 + 3a isolation tests still green; dotnet build wolverine.slnx -c Release clean.

Remaining plan follow-up

Only the CoalesceBy same-key poisoning refinement for ApplyItemException (flagged in #3302) remains — a small final PR.

🤖 Generated with Claude Code

…olation (GH-3289 Phase 3c)

Phase 3c of the #3289 batch-processing plan: item 2, the count-based sibling of
IsolateBatchMembers. For opaque batch failures with no exception type to key on:

  opts.BatchMessagesOf<Order>(b => b.ProbeIndividuallyAfter(attempts: 3));

retries the WHOLE batch N times (letting transient failures clear), then re-runs each
member as its own size-1 batch so only the genuinely bad one dead-letters.

- ProbeIndividuallyContinuation gains a probeAfterAttempts threshold: it requeues the
  whole batch (DeferAsync) while Envelope.Attempts < threshold, then probes. Size-<=1
  batches still dead-letter immediately (terminating case). IsolateBatchMembers keeps
  its threshold of 1 (probe on the first failure) - behavior unchanged.
- BatchingOptions.ProbeIndividuallyAfter(N) stores the threshold; a new startup step
  applyBatchProbePolicies() installs it as an every-attempt failure rule on the batch
  handler chain (batchChain.OnException<Exception>().ContinueWith(...)).

Test (DB-free): the whole 3-item batch is retried exactly 3 times, then the probe
isolates the poison item - the two healthy members succeed as singletons and only the
bad one is dead-lettered. Item 3 (IsolateBatchMembers) and 3a tests still green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller
jeremydmiller merged commit 8795088 into main Jul 5, 2026
26 checks passed
This was referenced Jul 9, 2026
This was referenced Jul 13, 2026
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.

1 participant