<!-- llms-explorer concept facts · https://llms-explorer.com/tree/pinned-secondary-retry-image-batch-rectification-and-delete-ordering-boundaries/ · pack 2026-11-02 · ~2212 tokens -->

# Pinned secondary retry-image batch rectification and delete ordering boundaries

> Source-anchored research for Pinned secondary retry-image batch rectification and delete ordering boundaries. Run status: COMPLETED.

Parent: [Retryable Writes](https://llms-explorer.com/tree/retryable-writes/) · 4 facets · 13 facts · page: https://llms-explorer.com/tree/pinned-secondary-retry-image-batch-rectification-and-delete-ordering-boundaries/

## Structure and components

- The original-entry fixtures deliberately select namespace ordering and one writer thread. ApplySessionDeleteBeforeEarlierRetryableUpdate and ApplySessionDeleteBeforeEarlierFirstRetryableUpdate submit update then delete and assert that the image collection has no next document while the user document contains the update. ApplySessionDeleteAfterLaterRetryableUpdate submits delete then update and asserts exactly the expected pre-image row and the updated user document. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp)

## How it works

- When a recognized effect supersedes the previous effect for the same logical session, shouldSkipOp replaces the stored pointer and clears the previous needsRetryImage flag if present. The earlier user-data operation remains eligible for application; the fixture with an earlier retryable update and a later delete asserts both an absent image row and an updated user document. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp)
- The real caller is OplogApplierImpl::_fillWriterVectors, which forwards to fillWriterVectors. That function calls deriveOpsAndFillWriterVectors with a session tracker. The derivation loop calls shouldSkipOp on original entries only when that tracker exists, and uses storeExtractedOpsAndDeletes for extracted operations. The later derivation call for flushed session-table updates passes a null tracker, keeping that separate materialized record outside this original-entry image check. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp)

## Comparisons and alternatives

- Recognized deletes are initially skipped rather than immediately added to writer vectors. After the scan, handleLatestDeletes invokes its handler only for final entries without needsRetryImage, asserts those entries are deletes, and clears the map. The final-delete handler calls addToWriterVector with the same arguments used for ordinary operation routing; it does not pass a forced writer ID. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_utils.cpp)
- The extraction helper explicitly assumes that extracted operations share a timestamp and that one extracted vector contains neither multiple implicit writes for one session nor an implicit write and a delete for the same session. Its comment uses these assumptions to justify registering surviving operations before extracted deletes, rather than preserving their interleaving. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp)
- Prepared image-table deletion is a source assumption with a debug assertion, rather than a demonstrated global impossibility: handleExtractedOpsAndRemoveDeletes uses dassert(!isPrepared) when removing an image delete, and the main derivation path carries TODO ([redacted]) to validate the assumption. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/util/assert_util_core.h)
- An entry with needsRetryImage must have a session identifier or the invariant fails. For an image-table delete, shouldSkipOp parses the document key as LogicalSessionId. Its FailedToParse catch logs warning 6796201 and calls dassert(false). If control continues after that catch, retryImageKey is unset and the function returns false instead of tracking or suppressing that delete. This catch names FailedToParse; it does not specify the outcome of every malformed BSON value. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/util/assert_util_core.h)

## Facts and statements

- At the pinned development source, RetryImageRectifier implements one last-effect-per-session contract for config.image_collection: it recognizes implicit CRUD image writes marked needsRetryImage and explicit session-reaper deletes. Other operations receive no special treatment from this rectifier. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp)
- shouldSkipOp requires original batch order and pointers to the operations that will actually be applied. The rectifier can mutate an earlier operation through its stored pointer. Extracted operations and extracted deletes remain in derivedOps until batch application completes; the applier declares derivedOps in the batch application scope before filling the writer vectors. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl.cpp)
- For extracted applyOps entries, handleExtractedOpsAndRemoveDeletes moves image-table deletes out of the extracted vector and erases the removed range before recording pointers. It then registers the surviving extracted operations and the separate deletes. storeExtractedOpsAndDeletes first moves the input vector into derivedOps, adds the separate delete vector there only if it is nonempty, and returns a reference to the stored surviving operations. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_dispatch.cpp)
- Worker application can change cross-namespace order: applyOplogBatchPerWorker calls applyOplogBatchCommon, which calls stableSortByNamespace. The sort preserves order within a namespace and sorts segments separated by prepared-transaction commands. The image rectification scan therefore precedes a worker ordering step that need not preserve the original cross-namespace sequence. (medium confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl.cpp) · [also](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_utils.cpp)
- The internal-transaction fixtures place needsRetryImage on an update inside applyOps. With that applyOps followed by a delete, the assertions require no image row and the updated user document. With the delete followed by the applyOps update, the assertions require exactly the expected pre-image row and the updated user document. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp)
- The extracted-delete fixtures place the image delete inside applyOps. ApplyApplyOpsSessionDeleteBeforeEarlierRetryableUpdate submits the retryable update first and asserts no image row plus the updated document. ApplyApplyOpsSessionDeleteAfterLaterRetryableUpdate submits the applyOps delete first and asserts exactly the expected pre-image row plus the updated document. These are fixture assertions about the same image side-table contract. (low confidence) — [source](https://raw.githubusercontent.com/mongodb/mongo/e37ae17db503703515d2ec35f6793dee7651655f/src/mongo/db/repl/oplog_applier_impl_test.cpp)
