Skip to content

backup: add live scan primitives#1065

Open
bootjp wants to merge 7 commits into
mainfrom
design/live-backup-scanner
Open

backup: add live scan primitives#1065
bootjp wants to merge 7 commits into
mainfrom
design/live-backup-scanner

Conversation

@bootjp

@bootjp bootjp commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Author: bootjp

Summary

  • Add MVCCStore.ScanKeysAt for key-only timestamp reads across in-memory and Pebble stores.
  • Add ShardStore.ScanKeysAt with route merging, leader-aware lock resolution, and LeaderRoutedStore forwarding.
  • Add BackupScanner paging over ShardStore.ScanAt for live logical backup producers.

Validation

  • go test ./store -run 'Test.*ScanKeysAt|TestEncryptionScanKeysAtHeaderTamperRejected' -count=1\n- go test ./kv -run 'TestShardStoreScanKeysAt|TestBackupScannerPaging' -count=1\n- go test ./store ./kv -count=1\n- go test ./... -run '^$' -count=1\n- golangci-lint run ./store ./kv --timeout=5m\n- git diff --check\n- git verify-commit HEAD

Summary by CodeRabbit

  • 新機能
    • 指定時点の可視キーだけを取得するキー一覧スキャン(ScanKeysAt)を追加しました。
    • バックアップ向けにページ単位で継続できるスキャン機能を追加しました。
  • 改善
    • 複数シャード/リーダー経由/プロキシ経由のキー走査で、結果の並び替えと重複除去、カーソル進行を強化しました。
    • 暗号化ストアでの改ざん検出を、キー一覧スキャンでも適用しました。

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c098e56e-210f-4484-9100-6c6728aecefd

📥 Commits

Reviewing files that changed from the base of the PR and between aa99e90 and 6cc845d.

📒 Files selected for processing (6)
  • kv/leader_routed_store.go
  • kv/shard_store.go
  • kv/shard_store_test.go
  • store/lsm_store.go
  • store/mvcc_store.go
  • store/scan_keys_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • kv/leader_routed_store.go
  • store/mvcc_store.go
  • kv/shard_store.go
  • store/lsm_store.go

📝 Walkthrough

Walkthrough

変更概要

指定時刻で可視なキーのみを取得するストアAPIを追加し、シャード横断のソート・重複排除・ルーティングを拡張しました。さらに、ページ単位で走査するバックアップスキャナと関連テストを追加しました。

Changes

キー走査とバックアップスキャン

Layer / File(s) Summary
キー専用ストアAPI
store/store.go, store/mvcc_store.go, store/lsm_store.go, store/scan_keys_test.go, store/lsm_store_encryption_test.go
ScanKeysAtをMVCCおよびPebbleストアに追加し、指定時刻で可視なキー、開始境界、compaction、暗号化ヘッダ検証を実装・検証しました。
シャード横断キー走査と前方ページング
kv/shard_store.go, kv/leader_routed_store.go, kv/leader_routed_store_test.go, kv/shard_store_test.go, kv/shard_store_txn_lock_test.go
ローカル・リーダー・プロキシ経路のキー走査、シャード横断のソート・重複排除、トランザクション内部キーの除外、前方KV走査のページングを追加し、ルーティングとロック解決を検証しました。
バックアップスキャナのページング
kv/backup_scan.go, kv/shard_store_test.go
BackupScannerNextClose、ページ取得、カーソル更新、空ページ・内部キーのみのページ・空キー・Pebble境界の処理を追加し、ページング動作を検証しました。

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant BackupScanner
  participant ShardStore
  participant StoreOrProxy
  Client->>BackupScanner: Next(ctx)
  BackupScanner->>ShardStore: scanRoutesAtSorted(cursor, end, pageSize, ts)
  ShardStore->>StoreOrProxy: ScanKeysAtまたはRawScanAt
  StoreOrProxy-->>ShardStore: 走査結果
  ShardStore-->>BackupScanner: ソート済みページ
  BackupScanner-->>Client: KVPairまたは終了
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.66% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed バックアップ用のライブ走査プリミティブ追加という主変更を簡潔に表しており、変更内容と整合しています。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

TLA+ spec divergence review (auto-triggered)

This PR touches files that the TLA+ safety spec has an anchor on (per
docs/design/2026_05_28_implemented_tla_safety_spec.md §3),
so an AI review is requested below to verify the implementation has not drifted
from the model.

Anchored files changed in this PR head (bd4a75c):

  • store/mvcc_store.go

What to check, by subsystem:

  • kv/hlc*.goNext() must respect the HLC-4 preconditions (i)/(ii)/(iii) from the design doc: bounded skew, logical-counter handoff on leader change (strategy (c) Observe(MaxAppliedHLC)), and the commit-time ceiling fence (fail-closed when wall_now >= physicalCeiling). Any change to the bit layout (48/16), the CAS loop, or the ceiling getter/setter is in scope.
  • kv/coordinator.go, kv/sharded_coordinator.goRunHLCLeaseRenewal, hlcRenewalInterval, hlcPhysicalWindowMs constants, and the new-term detection that calls Observe(fsm.MaxAppliedHLC()) (strategy (c)). Any change to renewal cadence, group selection, or fail-closed behaviour is in scope.
  • kv/transaction.go, kv/lock_resolver.go — OCC commit-ts assignment, lock-map encoding (key, lock_ts) -> start_ts, and the LockResolver action OCC-3 depends on. (M2 spec will land OCC-1..OCC-5; until then the spec doc §5.2 is the contract.)
  • kv/fsm.go — FSM apply of HLC lease entries (SetPhysicalCeiling), and any future MaxAppliedHLC() accessor that strategy (c) needs.
  • store/mvcc_store.go — version visibility, snapshot install, and the MVCC-1..MVCC-4 invariants (M3 scope).
  • distribution/** — route catalog versioning, SplitRange atomicity, and CatalogWatcher async fan-out (M4 scope).

If the change is correct but requires a spec update, edit tla/hlc/HLC.tla (or the corresponding M2..M5 module once landed) and the design doc in the same PR. The tla-check workflow runs the TLC model check on the same paths.


@claude review please verify TLA+ spec divergence per the checklist above.

@codex review please verify TLA+ spec divergence per the checklist above.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@bootjp

bootjp commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

Ready for review.

This implements the logical-backup scan primitive slice:

  • MVCCStore.ScanKeysAt for timestamp-explicit key-only scans.
  • ShardStore.ScanKeysAt with route merging and leader-side lock resolution.
  • BackupScanner paging over ShardStore.ScanAt.

Validation:

  • go test ./store -run 'Test.*ScanKeysAt|TestEncryptionScanKeysAtHeaderTamperRejected' -count=1\n- go test ./kv -run 'TestShardStoreScanKeysAt|TestBackupScannerPaging' -count=1\n- go test ./store ./kv -count=1\n- go test ./... -run '^$' -count=1\n- golangci-lint run ./store ./kv --timeout=5m\n- git diff --check\n- git verify-commit HEAD\n\n@codex review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new BackupScanner for paging through ShardStore scans without holding locks, and implements a ScanKeysAt method across various store layers (LeaderRoutedStore, ShardStore, MVCCStore, and pebbleStore) to fetch only keys visible at a given timestamp. The review feedback highlights a critical bug in BackupScanner where an empty last key can trigger an infinite loop by resetting the cursor instead of closing the scanner. Additionally, several redundant bytes.Clone operations were identified across the newly added methods, which should be removed to avoid unnecessary memory allocations.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread kv/backup_scan.go Outdated
Comment thread kv/backup_scan.go Outdated
Comment thread kv/leader_routed_store.go Outdated
Comment thread kv/shard_store.go
Comment thread store/lsm_store.go Outdated
@bootjp

bootjp commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

Addressed the current-head scan review findings.

Changes:

  • BackupScanner now marks the scan exhausted when a page cannot advance the cursor, avoiding a restart from the beginning while still returning the current page.
  • Added regression coverage for an empty-key page terminating after it is returned.
  • Removed redundant key/value clones where ownership is already provided by ScanAt, proxyRawScanAt, or Pebble decodeKey.

Validation:

  • go test ./kv -run 'TestBackupScanner|TestShardStoreScanKeysAt' -count=1\n- go test ./store -run 'Test.*ScanKeysAt|TestEncryptionScanKeysAtHeaderTamperRejected' -count=1\n- go test ./store ./kv -count=1\n- go test ./... -run '^$' -count=1\n- golangci-lint run ./store ./kv --timeout=5m\n- git diff --check\n- git verify-commit HEAD\n\n@codex review

@github-actions

Copy link
Copy Markdown
Contributor

TLA+ spec divergence review (auto-triggered)

This PR touches files that the TLA+ safety spec has an anchor on (per
docs/design/2026_05_28_implemented_tla_safety_spec.md §3),
so an AI review is requested below to verify the implementation has not drifted
from the model.

Anchored files changed in this PR head (a9f2581):

  • store/mvcc_store.go

What to check, by subsystem:

  • kv/hlc*.goNext() must respect the HLC-4 preconditions (i)/(ii)/(iii) from the design doc: bounded skew, logical-counter handoff on leader change (strategy (c) Observe(MaxAppliedHLC)), and the commit-time ceiling fence (fail-closed when wall_now >= physicalCeiling). Any change to the bit layout (48/16), the CAS loop, or the ceiling getter/setter is in scope.
  • kv/coordinator.go, kv/sharded_coordinator.goRunHLCLeaseRenewal, hlcRenewalInterval, hlcPhysicalWindowMs constants, and the new-term detection that calls Observe(fsm.MaxAppliedHLC()) (strategy (c)). Any change to renewal cadence, group selection, or fail-closed behaviour is in scope.
  • kv/transaction.go, kv/lock_resolver.go — OCC commit-ts assignment, lock-map encoding (key, lock_ts) -> start_ts, and the LockResolver action OCC-3 depends on. (M2 spec will land OCC-1..OCC-5; until then the spec doc §5.2 is the contract.)
  • kv/fsm.go — FSM apply of HLC lease entries (SetPhysicalCeiling), and any future MaxAppliedHLC() accessor that strategy (c) needs.
  • store/mvcc_store.go — version visibility, snapshot install, and the MVCC-1..MVCC-4 invariants (M3 scope).
  • distribution/** — route catalog versioning, SplitRange atomicity, and CatalogWatcher async fan-out (M4 scope).

If the change is correct but requires a spec update, edit tla/hlc/HLC.tla (or the corresponding M2..M5 module once landed) and the design doc in the same PR. The tla-check workflow runs the TLC model check on the same paths.


@claude review please verify TLA+ spec divergence per the checklist above.

@codex review please verify TLA+ spec divergence per the checklist above.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9f258151e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread kv/shard_store.go Outdated
Comment thread kv/shard_store.go
Comment thread kv/backup_scan.go Outdated
Comment thread kv/shard_store.go Outdated
@bootjp

bootjp commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

@codex review

対応しました。

  • 空 key を key-only scan helper で落とさないように修正
  • unclamped key scan で同一 GroupID の route を重複 scan しないように修正
  • backup scanner が空 key ページ後も 0x00 cursor で後続 key を読むように修正
  • key-only scan の merge/truncate を sort 後に行うように修正

検証:

  • go test ./kv -run "Test(BackupScanner|ShardStoreScanKeysAt|KeyOnlyScanHelpers|MergeAndTrimScanKeys)" -count=1
  • go test ./store -run "Test.*ScanKeysAt|TestEncryptionScanKeysAtHeaderTamperRejected" -count=1
  • go test ./store ./kv -count=1
  • go test ./... -run "^$" -count=1
  • golangci-lint run ./store ./kv --timeout=5m
  • git diff --check
  • git verify-commit HEAD

@github-actions

Copy link
Copy Markdown
Contributor

TLA+ spec divergence review (auto-triggered)

This PR touches files that the TLA+ safety spec has an anchor on (per
docs/design/2026_05_28_implemented_tla_safety_spec.md §3),
so an AI review is requested below to verify the implementation has not drifted
from the model.

Anchored files changed in this PR head (4b85955):

  • store/mvcc_store.go

What to check, by subsystem:

  • kv/hlc*.goNext() must respect the HLC-4 preconditions (i)/(ii)/(iii) from the design doc: bounded skew, logical-counter handoff on leader change (strategy (c) Observe(MaxAppliedHLC)), and the commit-time ceiling fence (fail-closed when wall_now >= physicalCeiling). Any change to the bit layout (48/16), the CAS loop, or the ceiling getter/setter is in scope.
  • kv/coordinator.go, kv/sharded_coordinator.goRunHLCLeaseRenewal, hlcRenewalInterval, hlcPhysicalWindowMs constants, and the new-term detection that calls Observe(fsm.MaxAppliedHLC()) (strategy (c)). Any change to renewal cadence, group selection, or fail-closed behaviour is in scope.
  • kv/transaction.go, kv/lock_resolver.go — OCC commit-ts assignment, lock-map encoding (key, lock_ts) -> start_ts, and the LockResolver action OCC-3 depends on. (M2 spec will land OCC-1..OCC-5; until then the spec doc §5.2 is the contract.)
  • kv/fsm.go — FSM apply of HLC lease entries (SetPhysicalCeiling), and any future MaxAppliedHLC() accessor that strategy (c) needs.
  • store/mvcc_store.go — version visibility, snapshot install, and the MVCC-1..MVCC-4 invariants (M3 scope).
  • distribution/** — route catalog versioning, SplitRange atomicity, and CatalogWatcher async fan-out (M4 scope).

If the change is correct but requires a spec update, edit tla/hlc/HLC.tla (or the corresponding M2..M5 module once landed) and the design doc in the same PR. The tla-check workflow runs the TLC model check on the same paths.


@claude review please verify TLA+ spec divergence per the checklist above.

@codex review please verify TLA+ spec divergence per the checklist above.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b859556f9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread kv/shard_store.go Outdated
Comment thread kv/shard_store.go Outdated
Comment thread kv/shard_store.go Outdated
Comment thread kv/backup_scan.go
@github-actions

Copy link
Copy Markdown
Contributor

TLA+ spec divergence review (auto-triggered)

This PR touches files that the TLA+ safety spec has an anchor on (per
docs/design/2026_05_28_implemented_tla_safety_spec.md §3),
so an AI review is requested below to verify the implementation has not drifted
from the model.

Anchored files changed in this PR head (582b2eb):

  • store/mvcc_store.go

What to check, by subsystem:

  • kv/hlc*.goNext() must respect the HLC-4 preconditions (i)/(ii)/(iii) from the design doc: bounded skew, logical-counter handoff on leader change (strategy (c) Observe(MaxAppliedHLC)), and the commit-time ceiling fence (fail-closed when wall_now >= physicalCeiling). Any change to the bit layout (48/16), the CAS loop, or the ceiling getter/setter is in scope.
  • kv/coordinator.go, kv/sharded_coordinator.goRunHLCLeaseRenewal, hlcRenewalInterval, hlcPhysicalWindowMs constants, and the new-term detection that calls Observe(fsm.MaxAppliedHLC()) (strategy (c)). Any change to renewal cadence, group selection, or fail-closed behaviour is in scope.
  • kv/transaction.go, kv/lock_resolver.go — OCC commit-ts assignment, lock-map encoding (key, lock_ts) -> start_ts, and the LockResolver action OCC-3 depends on. (M2 spec will land OCC-1..OCC-5; until then the spec doc §5.2 is the contract.)
  • kv/fsm.go — FSM apply of HLC lease entries (SetPhysicalCeiling), and any future MaxAppliedHLC() accessor that strategy (c) needs.
  • store/mvcc_store.go — version visibility, snapshot install, and the MVCC-1..MVCC-4 invariants (M3 scope).
  • distribution/** — route catalog versioning, SplitRange atomicity, and CatalogWatcher async fan-out (M4 scope).

If the change is correct but requires a spec update, edit tla/hlc/HLC.tla (or the corresponding M2..M5 module once landed) and the design doc in the same PR. The tla-check workflow runs the TLC model check on the same paths.


@claude review please verify TLA+ spec divergence per the checklist above.

@codex review please verify TLA+ spec divergence per the checklist above.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@bootjp

bootjp commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

@codex review

対応しました。

  • key-only scan の follower proxy が選択 route の GroupID を RawScanAt に渡すよう修正
  • local / leader / proxy の key-only scan で transaction-internal key を落とした後も limit まで refill
  • leader lock resolution 経路で空 key を nil と区別して保持
  • Pebble scan が nextScanCursor(lastKey) で同じ decoded user key を再読しないよう、start 未満の decoded key を skip
  • key-only merge は sort / dedupe 後に limit truncate

検証:

  • go test ./store -run 'TestPebbleStoreScan(At|KeysAt)CursorAfterKeyDoesNotRepeat|Test.*ScanKeysAt|TestEncryptionScanKeysAtHeaderTamperRejected' -count=1\n- go test ./kv -run 'Test(ShardStoreScanKeysRouteAtLeader|ShardStoreProxyScanKeysAt|BackupScannerPebblePaging|BackupScannerEmptyKey|BackupScannerPaging|ShardStoreScanKeysAt|KeyOnlyScanHelpers|MergeAndTrimScanKeys)' -count=1\n- go test ./store ./kv -count=1\n- go test ./... -run '^$' -count=1\n- golangci-lint run ./store ./kv --timeout=5m\n- git diff --check\n- git verify-commit HEAD

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 582b2eba2e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread kv/backup_scan.go
Comment thread kv/shard_store.go
Comment thread kv/backup_scan.go
Comment thread kv/shard_store.go
@github-actions

Copy link
Copy Markdown
Contributor

TLA+ spec divergence review (auto-triggered)

This PR touches files that the TLA+ safety spec has an anchor on (per
docs/design/2026_05_28_implemented_tla_safety_spec.md §3),
so an AI review is requested below to verify the implementation has not drifted
from the model.

Anchored files changed in this PR head (aa99e90):

  • store/mvcc_store.go

What to check, by subsystem:

  • kv/hlc*.goNext() must respect the HLC-4 preconditions (i)/(ii)/(iii) from the design doc: bounded skew, logical-counter handoff on leader change (strategy (c) Observe(MaxAppliedHLC)), and the commit-time ceiling fence (fail-closed when wall_now >= physicalCeiling). Any change to the bit layout (48/16), the CAS loop, or the ceiling getter/setter is in scope.
  • kv/coordinator.go, kv/sharded_coordinator.goRunHLCLeaseRenewal, hlcRenewalInterval, hlcPhysicalWindowMs constants, and the new-term detection that calls Observe(fsm.MaxAppliedHLC()) (strategy (c)). Any change to renewal cadence, group selection, or fail-closed behaviour is in scope.
  • kv/transaction.go, kv/lock_resolver.go — OCC commit-ts assignment, lock-map encoding (key, lock_ts) -> start_ts, and the LockResolver action OCC-3 depends on. (M2 spec will land OCC-1..OCC-5; until then the spec doc §5.2 is the contract.)
  • kv/fsm.go — FSM apply of HLC lease entries (SetPhysicalCeiling), and any future MaxAppliedHLC() accessor that strategy (c) needs.
  • store/mvcc_store.go — version visibility, snapshot install, and the MVCC-1..MVCC-4 invariants (M3 scope).
  • distribution/** — route catalog versioning, SplitRange atomicity, and CatalogWatcher async fan-out (M4 scope).

If the change is correct but requires a spec update, edit tla/hlc/HLC.tla (or the corresponding M2..M5 module once landed) and the design doc in the same PR. The tla-check workflow runs the TLC model check on the same paths.


@claude review please verify TLA+ spec divergence per the checklist above.

@codex review please verify TLA+ spec divergence per the checklist above.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@bootjp

bootjp commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

@codex review

対応しました。

  • BackupScanner が初期 scan scope の route set を保持し、list internal key を cursor にした後も full scan が単一 list group に縮まないよう修正
  • ShardStore の forward ScanAt / ScanGroupAt が transaction-internal page を落とした後も limit まで refill し、backup が空 filtered page で EOF 扱いしないよう修正
  • follower proxy scan は route ごとの selected GroupID を RawScanAt に渡し、leader 側 ScanGroupAt の refill 経路を使うよう修正
  • key-only leader scan で user-key page が空でも transaction lock rows を確認し、pending lock は ErrTxnLocked、committed secondary lock は key として返すよう修正

検証:

  • go test ./kv -run 'Test(BackupScannerPreservesFullRoutingAfterListKeyCursor|BackupScannerContinuesPastTxnInternalOnlyPage|ShardStoreProxyScanAtUsesSelectedGroup|ShardStoreProxyScanKeysAtUsesSelectedGroup|ShardStoreScanKeysAt_(ReturnsTxnLockedForPendingLockWithoutCommittedValue|ResolvesCommittedSecondaryLockWithoutCommittedValue)|ShardStoreScanAt_(ReturnsTxnLockedForPendingLockWithoutCommittedValue|ResolvesCommittedSecondaryLockWithoutCommittedValue)|ShardStoreScanKeysRouteAtLeaderRefillsAfterTxnInternalKeys)' -count=1
  • go test ./store -run 'TestPebbleStoreScan(At|KeysAt)CursorAfterKeyDoesNotRepeat|Test.*ScanKeysAt|TestEncryptionScanKeysAtHeaderTamperRejected' -count=1
  • go test ./store ./kv -count=1
  • go test ./... -run '^$' -count=1
  • golangci-lint run ./store ./kv --timeout=5m
  • git diff --check
  • git verify-commit HEAD

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
kv/leader_routed_store.go (1)

263-287: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

proxy 分岐のキー抽出を keysFromKVs に統一してください
手書きループだと kvp.Key == nil を落とせず、kv/shard_store.go の共通処理と挙動がずれます。return keysFromKVs(kvs), nil で十分です。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kv/leader_routed_store.go` around lines 263 - 287, Update
LeaderRoutedStore.ScanKeysAt’s proxy branch to replace the manual kvp iteration
with the shared keysFromKVs helper, returning its result directly with a nil
error and preserving the existing proxy error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@kv/shard_store.go`:
- Around line 634-734: Update the proxy branch of scanRouteAtForwardPage to
retain the unfiltered scan result separately, then filter only the returned kvs
while deriving advanceKey and full from the original raw page, matching the
local and leader branches. Preserve the existing proxy scan and filtering
behavior while ensuring pagination continues when raw results fill the requested
limit.
- Around line 295-339: The scanRoutesAt path must skip duplicate routes sharing
the same GroupID when clampToRoutes is false. Add seenGroups tracking and bypass
already-seen groups before calling scanRouteAt, matching scanKeyRoutesAt
behavior while preserving per-route scanning when clamping is enabled.

---

Nitpick comments:
In `@kv/leader_routed_store.go`:
- Around line 263-287: Update LeaderRoutedStore.ScanKeysAt’s proxy branch to
replace the manual kvp iteration with the shared keysFromKVs helper, returning
its result directly with a nil error and preserving the existing proxy error
handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 85010916-850a-4531-a052-aad914aa0d9f

📥 Commits

Reviewing files that changed from the base of the PR and between cd58354 and aa99e90.

📒 Files selected for processing (11)
  • kv/backup_scan.go
  • kv/leader_routed_store.go
  • kv/leader_routed_store_test.go
  • kv/shard_store.go
  • kv/shard_store_test.go
  • kv/shard_store_txn_lock_test.go
  • store/lsm_store.go
  • store/lsm_store_encryption_test.go
  • store/mvcc_store.go
  • store/scan_keys_test.go
  • store/store.go

Comment thread kv/shard_store.go
Comment thread kv/shard_store.go

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aa99e90709

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread kv/backup_scan.go
Comment thread kv/shard_store.go
Comment thread store/lsm_store.go
@github-actions

Copy link
Copy Markdown
Contributor

TLA+ spec divergence review (auto-triggered)

This PR touches files that the TLA+ safety spec has an anchor on (per
docs/design/2026_05_28_implemented_tla_safety_spec.md §3),
so an AI review is requested below to verify the implementation has not drifted
from the model.

Anchored files changed in this PR head (9adece8):

  • store/mvcc_store.go

What to check, by subsystem:

  • kv/hlc*.goNext() must respect the HLC-4 preconditions (i)/(ii)/(iii) from the design doc: bounded skew, logical-counter handoff on leader change (strategy (c) Observe(MaxAppliedHLC)), and the commit-time ceiling fence (fail-closed when wall_now >= physicalCeiling). Any change to the bit layout (48/16), the CAS loop, or the ceiling getter/setter is in scope.
  • kv/coordinator.go, kv/sharded_coordinator.goRunHLCLeaseRenewal, hlcRenewalInterval, hlcPhysicalWindowMs constants, and the new-term detection that calls Observe(fsm.MaxAppliedHLC()) (strategy (c)). Any change to renewal cadence, group selection, or fail-closed behaviour is in scope.
  • kv/transaction.go, kv/lock_resolver.go — OCC commit-ts assignment, lock-map encoding (key, lock_ts) -> start_ts, and the LockResolver action OCC-3 depends on. (M2 spec will land OCC-1..OCC-5; until then the spec doc §5.2 is the contract.)
  • kv/fsm.go — FSM apply of HLC lease entries (SetPhysicalCeiling), and any future MaxAppliedHLC() accessor that strategy (c) needs.
  • store/mvcc_store.go — version visibility, snapshot install, and the MVCC-1..MVCC-4 invariants (M3 scope).
  • distribution/** — route catalog versioning, SplitRange atomicity, and CatalogWatcher async fan-out (M4 scope).

If the change is correct but requires a spec update, edit tla/hlc/HLC.tla (or the corresponding M2..M5 module once landed) and the design doc in the same PR. The tla-check workflow runs the TLC model check on the same paths.


@claude review please verify TLA+ spec divergence per the checklist above.

@codex review please verify TLA+ spec divergence per the checklist above.

@bootjp

bootjp commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

@codex review

対応しました。

  • ScanAt の unclamped 走査でも同一 GroupID route を重複 scan しないよう修正
  • BackupScanner の unclamped full scan も同じ dedupe 経路で重複出力しないよう回帰テストを追加
  • follower proxy の forward ScanAt で filter 前 raw page から advance/full を判定し、txn internal key でページが早期終了しないよう修正
  • lock resolution 後に返却件数が limit に達した場合、内部 cursor を raw page 末尾へ進めず、返却行基準の次回 scan に任せるよう修正
  • ScanKeysAt の prefix-extension key を Pebble cursor skip で飛ばさないよう修正
  • LeaderRoutedStore の proxy key 抽出を keysFromKVs に統一

検証:

  • go test ./store -run 'TestPebbleStoreScan(At|KeysAt)(CursorAfterKeyDoesNotRepeat|PreservesPrefixExtensionKeys)|TestPebbleStoreScanKeysAtMatchesScanAtVisibility' -count=1\n- go test ./kv -run 'Test(ShardStoreScanAt_DeduplicatesUnclampedGroups|BackupScannerDeduplicatesUnclampedGroups|ShardStoreProxyForwardPageAdvancesFromRawPage|ShardStoreProxyScanAtUsesSelectedGroup|ShardStoreProxyScanKeysAtUsesSelectedGroup)' -count=1\n- go test ./store ./kv -count=1\n- go test ./kv -run 'Test(BackupScanner|ShardStoreScanAt_|ShardStoreScanKeysAt_|ShardStoreProxy|ShardStoreScanKeysRouteAtLeader|KeyOnlyScanHelpers|MergeAndTrimScanKeys)' -count=1\n- go test ./store -run 'Test.*ScanKeysAt|TestPebbleStoreScanAt|TestEncryptionScanKeysAtHeaderTamperRejected' -count=1\n- go test -race ./store ./kv -run 'Test(PebbleStoreScanAtPreservesPrefixExtensionKeys|PebbleStoreScanKeysAtPreservesPrefixExtensionKeys|ShardStoreScanAt_DeduplicatesUnclampedGroups|BackupScannerDeduplicatesUnclampedGroups|ShardStoreProxyForwardPageAdvancesFromRawPage)' -count=1\n- go test -race ./adapter -run 'Test_consistency_satisfy_write_after_read_sequence' -count=1\n- go test ./... -run '^$' -count=1\n- golangci-lint run ./store ./kv --timeout=5m\n- git diff --check\n- git verify-commit HEAD

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 9adece85e3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…anner

# Conflicts:
#	kv/leader_routed_store.go
#	kv/shard_store.go
#	store/lsm_store.go
#	store/mvcc_store.go
@bootjp

bootjp commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

Merged current main and resolved backup scanner scan conflicts. The resolved code keeps the main-branch physical-limit scan APIs and context checks, while preserving the live-backup ScanKeysAt / BackupScanner pagination fixes.

Validation:

  • go test ./store -run 'TestPebbleStoreScan(At|KeysAt)(CursorAfterKeyDoesNotRepeat|PreservesPrefixExtensionKeys)|TestPebbleStoreScanKeysAtMatchesScanAtVisibility|Test.*ScanKeysAt|TestEncryptionScanKeysAtHeaderTamperRejected' -count=1 -timeout=180s\n- go test ./kv -run 'Test(BackupScanner|ShardStoreScanAt_|ShardStoreScanKeysAt_|ShardStoreProxy|ShardStoreScanKeysRouteAtLeader|KeyOnlyScanHelpers|MergeAndTrimScanKeys)' -count=1 -timeout=240s\n- go test ./... -run '^$' -count=1 -timeout=300s\n- go test ./store ./kv -count=1 -timeout=240s\n- git diff --check\n- git diff --cached --check\n- git verify-commit HEAD\n\n@codex review

@github-actions

Copy link
Copy Markdown
Contributor

TLA+ spec divergence review (auto-triggered)

This PR touches files that the TLA+ safety spec has an anchor on (per
docs/design/2026_05_28_implemented_tla_safety_spec.md §3),
so an AI review is requested below to verify the implementation has not drifted
from the model.

Anchored files changed in this PR head (6cc845d):

  • store/mvcc_store.go

What to check, by subsystem:

  • kv/hlc*.goNext() must respect the HLC-4 preconditions (i)/(ii)/(iii) from the design doc: bounded skew, logical-counter handoff on leader change (strategy (c) Observe(MaxAppliedHLC)), and the commit-time ceiling fence (fail-closed when wall_now >= physicalCeiling). Any change to the bit layout (48/16), the CAS loop, or the ceiling getter/setter is in scope.
  • kv/coordinator.go, kv/sharded_coordinator.goRunHLCLeaseRenewal, hlcRenewalInterval, hlcPhysicalWindowMs constants, and the new-term detection that calls Observe(fsm.MaxAppliedHLC()) (strategy (c)). Any change to renewal cadence, group selection, or fail-closed behaviour is in scope.
  • kv/transaction.go, kv/lock_resolver.go — OCC commit-ts assignment, lock-map encoding (key, lock_ts) -> start_ts, and the LockResolver action OCC-3 depends on. (M2 spec will land OCC-1..OCC-5; until then the spec doc §5.2 is the contract.)
  • kv/fsm.go — FSM apply of HLC lease entries (SetPhysicalCeiling), and any future MaxAppliedHLC() accessor that strategy (c) needs.
  • store/mvcc_store.go — version visibility, snapshot install, and the MVCC-1..MVCC-4 invariants (M3 scope).
  • distribution/** — route catalog versioning, SplitRange atomicity, and CatalogWatcher async fan-out (M4 scope).

If the change is correct but requires a spec update, edit tla/hlc/HLC.tla (or the corresponding M2..M5 module once landed) and the design doc in the same PR. The tla-check workflow runs the TLC model check on the same paths.


@claude review please verify TLA+ spec divergence per the checklist above.

@codex review please verify TLA+ spec divergence per the checklist above.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 6cc845d01e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@bootjp

bootjp commented Jul 14, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Current head checked: 6cc845d01e4c33f1415a0eb86c9643a08359c605.

I rechecked the current-head top-level inline comments against the live code. No new code changes were needed; the current branch already contains the fixes for the latest-head review candidates:

  • kv/backup_scan.go: backup scanner keeps the original route set, so list-key cursors do not switch scan scope; it advances from returned rows and has regression coverage for empty keys, Pebble paging, txn-internal-only pages, and duplicate same-GroupID routes.
  • kv/shard_store.go: unclamped ScanAt and ScanKeysAt deduplicate same-GroupID routes; proxy forward pages derive advanceKey and full from the unfiltered raw page; key-only leader scans check lock-only ranges when user-key pages are empty.
  • store/lsm_store.go: forward Pebble scans skip decoded keys before start without jumping past prefix-extension keys.

Validation:

  • go test ./kv -run "Test(BackupScanner|ShardStoreScanAt_|ShardStoreScanKeysAt_|ShardStoreProxy|ShardStoreScanKeysRouteAtLeader|KeyOnlyScanHelpers|MergeAndTrimScanKeys)" -count=1
  • go test ./store -run "Test.*ScanKeysAt|TestPebbleStoreScanAtCursorAfterKeyDoesNotRepeat|TestPebbleStoreScanAtPreservesPrefixExtensionKeys|TestPebbleStoreScanKeysAtPreservesPrefixExtensionKeys|TestEncryptionScanKeysAtHeaderTamperRejected" -count=1
  • golangci-lint run ./store ./kv --timeout=5m
  • git diff --check

No commit was created because the worktree was already clean at the current PR head.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6cc845d01e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread store/lsm_store.go
func (s *pebbleStore) collectScanKeys(ctx context.Context, iter *pebble.Iterator, start, end []byte, limit int, ts uint64) ([][]byte, error) {
result := make([][]byte, 0, boundedScanResultCapacity(limit))

for iter.SeekGE(encodeKey(start, math.MaxUint64)); iter.Valid() && len(result) < limit; {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve logical ordering before truncating key scans

Because this new key-only scanner stops as soon as len(result) == limit while walking Pebble’s encoded-key order, it can return a later logical key before an earlier prefix key. User keys are allowed to contain arbitrary bytes; for example, with visible keys "\x00" and "\x00a", Pebble sorts the longer key first because the shorter key’s timestamp suffix compares after a, so ScanKeysAt(..., limit=1) returns "\x00a". ShardStore’s refill cursor then advances past "\x00", causing paginated key scans/backup counts to skip it. Please choose the first limit decoded user keys in logical byte order rather than truncating in physical iterator order.

Useful? React with 👍 / 👎.

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