Pinned event-mongodb outbox claim recovery and acknowledgment ownership
Parent: Change Data Capture Patterns · Published reference · snapshot 2026-11-02
↓ Facts as markdownall context files
Source-anchored research for Pinned event-mongodb outbox claim recovery and acknowledgment ownership. Run status: COMPLETED.
These notes link each claim to its source. Some citations identify archived research reports that are no longer hosted on this site. A published reference means the content is available; it does not certify independent review or accuracy.Read the editorial policy and follow the sources before relying on a claim.
Structure and components
- The mongoMessage document declares RetryCount with BSON key `retry_count`. `RecoverStuck` selects processing documents whose `claimed_at` is strictly earlier than the computed cutoff, changes them to pending, unsets `claimed_at` and `claimed_by`, and returns the modified count. Its filter does not check owner identity or owner liveness. Its complete update contains only the status assignment and removal of the claim fields; it does not increment the declared retry counter. (low confidence) [source]
Problems, failure modes and limitations
- In the pinned implementation, `claimBatch` returns no messages when `limit <= 0`; otherwise it finds candidate `_id` values whose `status` is pending or failed, ordered by descending `priority` and ascending `created_at`, with the requested limit. Candidate selection is a read before the claim update. (low confidence) [source]
- Claim readback filters candidate `_id` values by the generated `claimed_by` UUID and repeats the priority/age sort. That fetch has no status predicate. The function does not refill the candidate list after another relay wins documents, so the returned batch may be smaller than the requested limit. (low confidence) [source]
- The Fail method of mongoBatch likewise calls `b.store.collection.UpdateByID` with the ObjectID, sets failed status and `last_error`, and increments `retry_count`. A nil cause produces an empty error string. It supplies no owner or status predicate and does not unset the claim fields. Its Close method returns nil without an operation. (medium confidence) [source 1] [source 2]
- Code-level inference: recovery clears the claim UUID but preserves document identity, whereas Ack and Fail target only the ObjectID with `b.store.collection.UpdateByID`. A message retained by an earlier owner can therefore target the same extant document after recovery and reclamation; these methods contain no current-status or current-owner condition to reject that stale operation. This is a filter-based inference, not an observed race or a production incident. (low confidence) [source]
- The ordinary Ack fixture asserts published status. The ordinary Fail fixture asserts failed status, a retry count of 1, and the stored error text. Neither fixture interleaves recovery or a successor claim with the acknowledgment. (low confidence) [source]
- The relay fixtures assert eventual published state after polling and live insertion, failed state on a transport error, and two recorded publishes plus two published documents after PublishOnce. Their recording transport records a successful Publish call in memory and returns a configured transport error before recording. These fixture bodies do not simulate a process crash after publish succeeds and before acknowledgment, or an acknowledgment write failure. They do not prove exactly-once external publication across that boundary; these are source assertions, not executed results. (low confidence) [source]
Facts and statements
- The claim write generates a UUID `claimToken` and uses `UpdateMany` with both candidate `_id` membership and a fresh pending-or-failed `status` predicate. It sets processing status, `claimed_at`, and `claimed_by`. The implementation describes the status check as atomic per document; it does not wrap the candidate read and batch update in one transaction. (low confidence) [source]
- `toClaimedMessage` stashes the document ObjectID with `evtoutbox.NewClaimedMessage(msg, m.ID)`. The unit fixture `TestMongoMessageToClaimedMessage` explicitly checks that the recovered token has type `bson.ObjectID` and equals the original ObjectID. This is a source assertion, not an executed result. (medium confidence) [source 1] [source 2]
- The Ack method of mongoBatch requires an ObjectID token and calls `b.store.collection.UpdateByID` to set published status and `published_at`. It checks for a missing match but supplies no claim-owner, claim-age, processing-status, or batch-membership predicate; it does not unset the claim fields. (medium confidence) [source 1] [source 2]
- The fixture `TestIntegrationClaimBatchConcurrencySafe` makes sequential claims and asserts that already-processing messages are not claimed again. Separately, `TestIntegrationConcurrentClaimNoDuplicates` seeds 20 events, launches 5 claiming goroutines, and asserts one observation per event and complete coverage. These are source assertions, not execution results from this research. (low confidence) [source]
- `TestIntegrationRecoverStuck` seeds a processing message claimed `30` minutes ago and a freshly claimed processing message, invokes recovery with a `5` minute threshold, and asserts one recovered, one pending, and one processing document. Its assertions do not read back cleared claim fields or exercise a live old owner after recovery. (low confidence) [source]
- `TestMongoStoreConformance` delegates to `evtoutbox.RunStoreConformance` with a seed function and a live MongoStore. Its local source says the test skips without reachable MongoDB. The wrapper itself provides no stale-owner or publication/acknowledgment crash assertions, and delegation is not evidence that the external suite passed. (low confidence) [source]
- `TestIntegrationRelayRecoverStuckViaStart` seeds an old processing message and configures the generic relay with a `20` millisecond stuck-check interval and a `5` minute threshold. It waits for at least one published document and at least one recording-transport publication. These lower-bound assertions do not establish a single publication or simulate a stale worker completing after recovery. (low confidence) [source]
Children
- No children recorded.