feat(batching): IsolateBatchMembers error policy for opaque batch failures (GH-3289 Phase 3b)#3311
Merged
Merged
Conversation
…lures (GH-3289 Phase 3b) Phase 3b of the #3289 batch-processing plan: item 3. For an OPAQUE batch failure (the handler throws but can't name the bad item), the new error policy opts.Policies.OnException<ValidationException>().IsolateBatchMembers(); re-runs each member of the failed batch as its own size-1 batch (via 3a's shared BatchReplay primitive), so only the member that actually reproduces the failure is dead-lettered while the healthy members succeed. - New ProbeIndividuallyContinuation(+Source): splits a batch (>1 member) into singletons; a size-<=1 batch is dead-lettered (the terminating/base case, so a probed singleton that fails again just DLQs). - New IsolateBatchMembers() verb on IFailureActions / FailureActions / PolicyExpression, installed as an every-attempt ContinueWith. Composes with the retry verbs by exception type: a transient SqlException can RetryWithCooldown the whole batch while a deterministic ValidationException isolates. Tests (DB-free): opaque-failure isolation (only the bad item dead-letters, healthy members succeed, captured via IDeadLetterInterceptor) + non-batched fallback to plain dead-lettering. 253 error-handling/batch tests still green. Follow-ups (called out in docs): count-based ProbeIndividuallyAfter(N) (item 2) and poisoning every member that collapsed into a coalesced CoalesceBy key. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 9, 2026
Merged
This was referenced Jul 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 3b of the #3289 batch-processing plan: item 3 (
IsolateBatchMembers). (Phases 0/1/2/3a merged as #3299/#3300/#3301/#3302.)The feature
Item 8 (
ApplyItemException, #3302) handles failures the handler can name. This handles the opaque case — the batch handler throws but can't attribute it to a specific item. The new exception-type-keyed error policy isolates the culprit anyway:IsolateBatchMembers()re-runs each member of the failed batch as its own size-1 batch (via the sharedBatchReplayprimitive from 3a), so only the member that actually reproduces the failure is dead-lettered while the healthy members succeed.Implementation
ProbeIndividuallyContinuation(+Source) — splits a batch (>1 member) into singletons; a size-≤1 batch is dead-lettered. That size-≤1 guard is the terminating/base case: a probed singleton that fails again just DLQs (no infinite re-probe) and it's also the "no effect on non-batched messages" path.IsolateBatchMembers()verb — added toIFailureActions/FailureActions/PolicyExpression, installed as an every-attemptContinueWith. Composes with the retry verbs purely by exception-type matching (separateFailureRules), exactly as the plan's flagship example shows.Tests (DB-free)
src/Testing/CoreTests/Acceptance/batch_isolate_members.cs:[good1, bad, good2]throws → probed into singletons → the two healthy items succeed and onlybadis dead-lettered (captured via anIDeadLetterInterceptor, which runs underNullMessageStore);Both green; 253 existing error-handling/batch tests still pass.
dotnet build wolverine.slnx -c Releaseclean.Remaining plan follow-ups
ProbeIndividuallyAfter(attempts: N): the count-based variant (probe only after N whole-batch failures) — needs a per-batch-chain threshold; next PR.CoalesceBysame-key poisoning forApplyItemException(flagged in feat(batching): ApplyItemException to isolate poison items from a batch (GH-3289 Phase 3a) #3302): a small follow-up.🤖 Generated with Claude Code