Skip to content

feat(batching): ApplyItemException poisons every member of a coalesced key (GH-3289 Phase 3d)#3313

Merged
jeremydmiller merged 1 commit into
mainfrom
feat-batching-phase3d-coalesce-poison-3289
Jul 5, 2026
Merged

feat(batching): ApplyItemException poisons every member of a coalesced key (GH-3289 Phase 3d)#3313
jeremydmiller merged 1 commit into
mainfrom
feat-batching-phase3d-coalesce-poison-3289

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Final follow-up of the #3289 batch-processing plan: the CoalesceBy × ApplyItemException interplay flagged as a deliberate follow-up in #3302.

The gap

Under CoalesceBy, the handler only sees the last-wins instance for a key. ApplyItemException matched poison items by reference identity, so flagging the coalesced item dead-lettered only that one member and left the earlier same-key members in the survivor set (acked/replayed). The plan calls for poisoning every member that collapsed into a flagged key.

Fix

  • New internal Envelope.BatchGroupId ([JsonIgnore], reset in Reset()) — the coalesced-group index, stamped per key by CoalescingMessageBatcher; null for a normal (non-coalesced) batch.
  • ApplyItemContinuation expands the poison set to all members sharing a poisoned member's BatchGroupId. It's a no-op when BatchGroupId is null, so the existing reference-identity behavior for normal batches is unchanged.

Test (DB-free)

batch_coalesce_poison.cs: a key "A" with three members (v1, v2, v3) whose coalesced last-wins (v3) is poison → all three A versions are dead-lettered, while the healthy key "B" survives and is replayed to success (captured via IDeadLetterInterceptor). The 3a ApplyItemException and Phase-1 CoalesceBy tests still pass; dotnet build wolverine.slnx -c Release clean.

Plan status

This completes the actionable items of the #3289 plan:

  • 0 docs, 1 CoalesceBy+IBatchContext, 2 collision diagnostic, 3a ApplyItemException, 3b IsolateBatchMembers, 3c ProbeIndividuallyAfter, and this 3d refinement.
  • The plan's explicit not-in-scope items (deferred inline settlement / item 7, lock-budget startup warning / item 4) were documentation-only and are covered by the Phase 0 settlement section.

🤖 Generated with Claude Code

…d key (GH-3289 Phase 3d)

Final follow-up of the #3289 batch-processing plan: the CoalesceBy interplay
flagged in #3302. Under CoalesceBy the handler only sees the last-wins instance
for a key, so ApplyItemException previously dead-lettered only that one member and
left the earlier same-key members in the survivor set. Now flagging a coalesced item
poisons EVERY member that collapsed into that key.

- New internal Envelope.BatchGroupId (JsonIgnore, reset in Reset()): the coalesced
  group index, stamped per key by CoalescingMessageBatcher; null for normal batches.
- ApplyItemContinuation expands the poison set to all members sharing a poisoned
  member's BatchGroupId. No-op when BatchGroupId is null (non-coalesced batch), so
  existing reference-identity behavior is unchanged.

Test (DB-free): a key with three members whose coalesced last-wins is poison
dead-letters all three versions, while the healthy key survives and is replayed to
success. 3a ApplyItemException + Phase 1 CoalesceBy tests still green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller
jeremydmiller merged commit c38f124 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