Skip to content

CBG-5291: CAS-safe Update on dual MetadataStore wrapper#8238

Open
bbrks wants to merge 1 commit intomainfrom
CBG-5291
Open

CBG-5291: CAS-safe Update on dual MetadataStore wrapper#8238
bbrks wants to merge 1 commit intomainfrom
CBG-5291

Conversation

@bbrks
Copy link
Copy Markdown
Member

@bbrks bbrks commented May 6, 2026

CBG-5291

MetadataStore.Update previously delegated the entire read-modify-write to the fallback datastore

Implements a MetadataStore wrapper-level CAS retry loop that always writes to primary, even when the doc lives only in the fallback store.

  • Same dual-read pattern applied to MetadataStore.WriteUpdateWithXattrs
  • New tests cover: doc-only-in-fallback (callback sees fallback value, result lands in primary, fallback untouched), doc-in-primary (primary takes precedence), isDelete for fallback-only doc (no-op — migration sweep handles cleanup), post-SetMigrationComplete behaviour, and the xattr analogue of the migration case.

Why this is CAS-safe

The wrapper invariant — no writes ever go to fallback while the dual-store is in use — means the only writer to either store is this wrapper writing to primary. So the loop:

  1. Probe primary.Exists. If found (or migration is sealed), delegate to primary.Update / primary.WriteUpdateWithXattrs — those already have correct CAS retry loops.
  2. Otherwise read the doc from fallback, feed it to the caller's callback, and WriteCas/WriteWithXattrs with cas=0 (insert) into primary.
  3. On IsCasMismatch (covers both gocb.ErrDocumentExists and rosmar CasMismatchErr), retry from step 1 — by now primary holds the doc, so we go through the standard primary CAS path.

Integration Tests

Replaces the placeholder MetadataStore.Update (which delegated the entire
read-modify-write to the fallback datastore) with a wrapper-level CAS
retry loop that always lands writes in primary. When the doc is in
primary or the doc is absent from both stores, it delegates to
primary.Update; when the doc lives only in fallback, it feeds the
fallback value to the caller's callback and inserts the result into
primary via WriteCas, retrying on CAS race. A delete returned by the
callback for a fallback-only doc is a no-op in primary - the metadata
migration sweep tombstones the fallback copy.

WriteUpdateWithXattrs gets the same dual-read pattern for symmetry
(callers today are application-data only, but a future metadata caller
would otherwise silently skip fallback data).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 6, 2026 14:58
@bbrks bbrks requested a review from gregns1 May 6, 2026 16:36
@bbrks bbrks removed their assignment May 6, 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.

2 participants