Skip to content

distribution: add migration wire contracts#1084

Open
bootjp wants to merge 17 commits into
mainfrom
design/hotspot-split-m2-wire
Open

distribution: add migration wire contracts#1084
bootjp wants to merge 17 commits into
mainfrom
design/hotspot-split-m2-wire

Conversation

@bootjp

@bootjp bootjp commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • add M2 migration RPCs and internal export/import wire contracts, with generated protobuf code
  • add RouteDescriptor migration fields to protobuf and durable route codec v2 while preserving v1 encoding for zero-field routes
  • plumb migration route fields through ListRoutes responses and cover the codec/protobuf conversion paths

Tests

  • make -C proto check-tools
  • make -C proto gen
  • go test ./distribution -count=1 -timeout=120s
  • go test ./adapter -run 'TestDistributionServer|TestMilestone1SplitRange' -count=1 -timeout=180s
  • go test ./kv ./proto -count=1 -timeout=180s
  • GOCACHE=$(pwd)/.cache GOLANGCI_LINT_CACHE=$(pwd)/.golangci-cache golangci-lint run ./distribution ./adapter --timeout=5m
  • git diff --check

Note: full adapter-package testing exceeded the local timeout in existing raft/gRPC integration coverage; the targeted distribution adapter tests above passed.

Author: bootjp

Summary by CodeRabbit

  • 新機能
    • ルート分割移行の新RPC(開始、所有者/交差ルート取得、ジョブ一覧、再試行・中止)に対応。
    • MVCC範囲バージョンのエクスポート/インポートを追加。
    • 読み取りフェンス付きRawGet/RawLatestCommitTS/RawScanAtで、ルート境界付きの読み取りに対応。
  • 改善
    • 分割・移行中ルートのメタデータ(staged visibility / migration job / min write ts)を保存・復元・応答まで一貫反映。
    • ルート境界付き逆方向スキャンの許容範囲を読み取りフェンス有効時に条件付き最適化。
  • テスト
    • ルート境界・フェンス・分割移行メタデータ等の検証を追加/拡充。

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

ルート移行メタデータ

Layer / File(s) Summary
移行APIとルート契約
proto/distribution.proto, proto/internal.proto
分割移行、分割ジョブ、MVCC範囲転送RPCと移行状態フィールドを追加します。
カタログcodecと保存処理
distribution/catalog.go, distribution/catalog_test.go
RouteDescriptorのv1/v2 codec、移行フィールドの検証・比較・clone、MinWriteTSExclusiveの単調保存を追加します。
エンジンとDistributionへの伝播
distribution/engine.go, distribution/engine_test.go, adapter/distribution_server.go, adapter/distribution_server_test.go
移行フィールドをEngine、分割後ルート、Distributionのprotobuf応答へ伝播します。

読み取りフェンス付きルーティング

Layer / File(s) Summary
読み取りフェンスRPC契約
proto/service.proto
Raw読み取りリクエストにread route versionとルート境界情報を追加します。
gRPC Raw読み取り分岐
adapter/grpc.go, adapter/grpc_test.go
read fence対応ストアを優先し、route version・境界の決定とgrouped reverseの検証を行います。
LeaderRoutedStoreのフェンス読み取り
kv/leader_routed_store.go, kv/leader_routed_store_test.go
ローカル読み取りとRaw RPCフォールバックをread fence対応APIへ拡張します。
ShardStoreの境界付きスキャン
kv/shard_store.go, kv/shard_store_test.go, kv/shard_store_txn_lock_test.go
境界付き順方向・逆方向スキャン、ルートフィルタ、ロック走査、read route version伝播を追加します。

Redisキー正規化

Layer / File(s) Summary
Redis wide-columnキーの正規化
kv/shard_key.go, kv/shard_key_test.go
Hash、Set、ZSetの内部キーを共通のユーザーキーへ正規化します。

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant GRPCServer
  participant LeaderRoutedStore
  participant ShardStore
  Client->>GRPCServer: RawScanAt(read route version, route bounds)
  GRPCServer->>LeaderRoutedStore: ScanAtWithReadFence
  LeaderRoutedStore->>ShardStore: 境界付きローカルスキャンまたはRaw RPC
  ShardStore-->>LeaderRoutedStore: フェンス済みKV結果
  LeaderRoutedStore-->>GRPCServer: ScanAt結果
  GRPCServer-->>Client: RawScanAt応答
Loading

Possibly related PRs

  • bootjp/elastickv#1065: RawScanAt のKeysOnly経路と rawScanKeysAt への委譲が関連します。
  • bootjp/elastickv#1117: RouteDescriptor v2とカタログ移行フィールドの変更が、カタログdeltaの公開・適用処理と関連します。
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.28% 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.

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 (72fcc6b):

  • distribution/catalog.go
  • distribution/catalog_test.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 13, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

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

@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 V2 codec version for route descriptors in the distribution catalog to support new migration-related fields, including staged visibility, migration job IDs, and exclusive write timestamps. It also updates protobuf definitions and generated gRPC code to add several new RPC methods (such as split migration and range version export/import) and includes read route versions for migration read fences. The review feedback suggests defining an explicit catalogRouteCodecVersionV2 constant instead of using the dynamic catalogRouteCodecVersion directly in encoding and decoding paths, which prevents future codec version bumps from breaking V2-specific logic.

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 distribution/catalog.go Outdated
Comment thread distribution/catalog.go
Comment thread distribution/catalog.go Outdated
@bootjp

bootjp commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

@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 (7dd2e6d):

  • distribution/catalog.go
  • distribution/catalog_test.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: 7dd2e6d48a

ℹ️ 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 distribution/catalog.go
Comment thread proto/service.proto Outdated
Comment thread distribution/catalog.go
@bootjp

bootjp commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Addressed current-head blockers in ef2ba76:

  • preserved MinWriteTSExclusive and migration fields when splitting/catalog snapshotting routes
  • carried migration fields into distribution.Route snapshots and stats/intersection paths
  • forwarded read_route_version and scan route bounds through raw read proxy hops

Validation:

  • go test ./adapter -run 'TestDistributionServerSplitRange_Success|TestDistributionServerListRoutes_ReadsDurableCatalog' -count=1
  • go test ./distribution -count=1
  • go test ./kv -count=1
  • go test ./adapter ./distribution ./kv -run '^$' -count=1
  • golangci-lint --config=.golangci.yaml run ./adapter ./distribution ./kv --timeout=5m
  • git diff --check HEAD~1..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 (ef2ba76):

  • distribution/catalog.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.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 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: ef2ba76416

ℹ️ 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
Comment thread distribution/catalog.go Outdated
Comment thread adapter/grpc.go Outdated
var err error
if groupID := req.GetGroupId(); groupID != 0 {
if fenceGetter, ok := r.store.(rawReadFenceGetter); ok {
v, err = fenceGetter.GetAtWithReadFence(ctx, req.Key, readTS, req.GetGroupId(), req.GetReadRouteVersion())

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 Stamp raw reads before using the fence helper

External RawKV callers leave read_route_version unset, but this branch passes that zero straight into the fenced store path instead of stamping the catalog version observed while routing the request. When this server is a follower and proxies the read during a split migration, the internal RawGet still carries version 0, so the source-side cutover fence either treats a fresh routed read as a broken legacy hop once zero-version rejection is active or cannot distinguish it from a stale coordinator request; stamp the current route/catalog version before invoking the fence helper.

Useful? React with 👍 / 👎.

@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 (2388b3e):

  • distribution/catalog.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.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 13, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Addressed the current-head blockers in 2388b3e:

  • routed fenced ShardStore scans using supplied route_start/route_end while keeping the raw scan bounds for storage reads
  • kept CatalogStore MinWriteTSExclusive monotone by merging existing and desired descriptors with max(existing, desired)
  • stamped zero read_route_version at the RawKV gRPC entrypoint before invoking read-fence helper paths, while preserving caller-supplied stamps

Validation:

  • go test ./kv ./distribution ./adapter -run 'TestShardStoreScanAtWithReadFence_RoutesUsingSuppliedBounds|TestCatalogStoreSaveKeepsMinWriteTSExclusiveMonotone|TestGRPCServer_RawReadFenceHelpersStampCurrentRouteVersion|TestGRPCServer_RawReadFenceHelpersKeepCallerRouteVersion' -count=1
  • git diff --check
  • golangci-lint run ./... --timeout=5m --allow-serial-runners
  • commit hook: golangci-lint --config=.golangci.yaml run --fix (0 issues)
  • go test ./... was run: the initial parallel run failed with no space left on device; the retry with TMPDIR=.tmp GOTMPDIR=.tmp GOCACHE=.gocache go test -p=1 ./... passed root/distribution/kv/store and remaining packages, but adapter timed out at 600s

@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: 2388b3e665

ℹ️ 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 adapter/grpc.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 (781dc36):

  • distribution/catalog.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.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 13, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Addressed the current-head fenced raw scan findings in 781dc36:

  • preserved InvalidArgument for RawScanAt requests that combine group_id and reverse before the read-fence helper path can handle them
  • deduplicated same-group ShardStore read-fence scans only when supplied route_start/route_end causes raw storage bounds to be reused across adjacent descriptors

Validation:

  • go test ./adapter ./kv -run TestGRPCServer_RawScanAt_GroupedReverseStaysInvalidArgumentWithReadFenceStore|TestShardStoreScanAtWithReadFence_DeduplicatesSameGroupSuppliedBounds|TestShardStoreScanAtWithReadFence_RoutesUsingSuppliedBounds|TestGRPCServer_RawReadFenceHelpersStampCurrentRouteVersion|TestGRPCServer_RawReadFenceHelpersKeepCallerRouteVersion -count=1
  • golangci-lint --config=.golangci.yaml run ./adapter ./kv --timeout=5m
  • git diff --check HEAD~1..HEAD
  • commit hook: golangci-lint --config=.golangci.yaml run --fix (0 issues)

@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: 781dc362ec

ℹ️ 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
Comment thread kv/shard_store.go Outdated
@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 (1afde8f):

  • distribution/catalog.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.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 14, 2026

Copy link
Copy Markdown
Owner Author

Fixed the two RawScanAt fence findings:

  • Added explicit route-bound presence on RawScanAt and threaded it through ShardStore/LeaderRoutedStore proxy requests so the logical ["", +infinity) range survives proto3 empty bytes.
  • Added route-key-filtered pagination for supplied-bound scans so same-group sibling route rows are skipped without leaking rows or short-filling pages.

Caller audit:

  • rg "ScanAtWithReadFence\(" only finds the adapter RawScanAt path, ShardStore/LeaderRoutedStore proxy paths, and tests; no broader call sites required API changes.

Validation:

  • go test ./kv
  • go test ./adapter -run "TestGRPCServer_RawScanAt_PreservesFullRangeRouteBoundsPresence|TestGRPCServer_RawReadFenceHelpersKeepCallerRouteVersion|TestGRPCServer_RawScanAt_GroupedReverseStaysInvalidArgumentWithReadFenceStore" -count=1
  • golangci-lint run ./adapter ./kv --timeout=5m
  • git diff --check
  • buf generate

@codex review

@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: 1afde8f1ba

ℹ️ 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/leader_routed_store.go Outdated
Comment on lines +222 to +226
if reverse {
kvs, err := s.local.ReverseScanAt(ctx, start, end, limit, max(ts, fenceTS))
return kvs, errors.WithStack(err)
}
kvs, err := s.local.ScanAt(ctx, start, end, limit, max(ts, fenceTS))

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 Honor route bounds on local leader scans

When this store is the verified local leader and a RawScanAt/ScanAtWithReadFence call supplies routeStart/routeEnd, these branches read the local MVCC store directly and never apply the route-key filter/pagination that the ShardStore path uses. In a leader-routed deployment receiving a supplied-bound scan over an internal raw prefix, rows from same-group sibling route intervals can be returned or consume the page limit, while the non-leader proxy path preserves the bounds.

Useful? React with 👍 / 👎.

Comment thread kv/shard_store.go Outdated
scanEnd := end
for len(out) < limit {
batchLimit := routeFilteredScanBatchLimit(limit - len(out))
kvs, err := s.scanRouteAtDirectionWithReadFenceOnce(ctx, route, scanStart, scanEnd, batchLimit, ts, reverse, explicitGroup, readRouteVersion, routeStart, routeEnd)

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 Filter route keys before resolving scan locks

For supplied-bound scans on a local ShardStore leader, this call resolves MVCC/txn locks for the raw batch before appendRouteFilteredKVs drops rows whose routeKey is outside routeStart/routeEnd. If a same-group sibling route has a pending lock under the scanned raw prefix, the bounded scan can return ErrTxnLocked or hit the lock budget even though that sibling row should be skipped by the route filter.

Useful? React with 👍 / 👎.

@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 (33c793f):

  • distribution/catalog.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.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 14, 2026

Copy link
Copy Markdown
Owner Author

Fixed the two current-head review findings.

Summary:

  • Local LeaderRoutedStore.ScanAtWithReadFence now applies route-key bounded pagination before returning verified-local-leader scan results, including reverse scans.
  • Local ShardStore leader supplied-bound scans now keep raw scan pages for cursor movement while filtering visible KVs and txn-lock KVs by route key before lock resolution. Same-group sibling route locks are skipped before they can return ErrTxnLocked or consume the lock budget.

Caller audit:

  • RawScanAt decodes RouteBoundsPresent/RouteStart/RouteEnd in adapter/grpc.go and forwards them through ScanAtWithReadFence.
  • The proxy RawScan path already forwards route bounds on the wire.
  • Grep found no other route-bound scan callers outside the grpc RawScan/read-fence path, the kv scan/read-fence implementation/tests, and internal/s3keys route-bound construction.

Validation:

  • go test ./kv -run 'TestLeaderRoutedStore_ScanAtWithReadFenceFiltersRouteBoundsLocally|TestShardStoreScanAtWithReadFence_SkipsOutOfRoutePendingLock|TestShardStoreScanAtWithReadFence_FiltersSuppliedBoundsByRouteKey'
  • go test ./kv
  • go test ./adapter -run 'Test_grpc_scan|TestGRPCServer_RawScanAt|TestGRPCServer_RawReadFenceHelpers'
  • golangci-lint run ./... --timeout=5m
  • git diff --check
  • Attempted go test ./...; all reported packages passed except the broad adapter package hit the Go test 600s timeout. The targeted adapter RawScan coverage above passed.

Commit: 33c793f

@codex review

@bootjp

bootjp commented Jul 14, 2026

Copy link
Copy Markdown
Owner Author

Addressed the latest current-head route-bounded local scan findings in 33c793f.

Changes:

  • local LeaderRoutedStore read-fence scans now apply route-key filtering/pagination when route_start/route_end are supplied
  • local ShardStore leader scans now filter route keys before resolving MVCC/txn locks, so sibling-route locks cannot leak into bounded scans
  • added regression coverage for local leader route-bounded scans and out-of-route pending locks

Validation:

  • go test ./kv -run 'TestLeaderRoutedStore|TestShardStore|Test.*Route.*Scan|Test.*ReadFence|Test.Lock' -count=1 -timeout=180s\n- golangci-lint --config=.golangci.yaml run ./kv --timeout=5m\n- git diff --check HEAD~1..HEAD\n\nCaller audit:\n- rg -n "ScanAtWithReadFence|RawScanAt\(|appendRouteFilteredKVs|resolveLocksForKVs|routeStart|routeEnd" kv -g'.go'\n\n@codex review

@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: 33c793f03d

ℹ️ 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 on lines +544 to +548
var groupID uint64
if explicitGroup {
groupID = route.GroupID
}
kvs, err := s.proxyRawScanAt(ctx, g, start, end, limit, ts, reverse, groupID, readRouteVersion, routeStart, routeEnd)

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 the target group on proxied route-bound scans

When a supplied route-bound scan falls into this follower branch with explicitGroup == false, groupID remains zero, so the RawScanAt sent to this route's leader is re-routed there as a multi-route scan using the supplied route bounds. On nodes that host or know multiple shard groups, that leader can return sibling-group rows; the caller then scans those sibling routes again in scanRoutesAtWithReadFence, producing duplicates and applying the page limit to the wrong combined set. The proxied route-bounded request needs to stay scoped to route.GroupID instead of relying on the receiver to rediscover routes.

Useful? React with 👍 / 👎.

@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 (a456f48):

  • distribution/catalog.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.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 force-pushed the design/hotspot-split-m2-wire branch from 707cc61 to 0b3b1d1 Compare July 23, 2026 08:52
@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 (0b3b1d1):

  • distribution/catalog.go
  • distribution/catalog_delta.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.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 force-pushed the design/hotspot-split-m2-wire branch from 0b3b1d1 to 6b40846 Compare July 23, 2026 09:11
@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 (6b40846):

  • distribution/catalog.go
  • distribution/catalog_delta.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.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 force-pushed the design/hotspot-split-m2-wire branch from 6b40846 to 644fd08 Compare July 23, 2026 09:18
@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 (644fd08):

  • distribution/catalog.go
  • distribution/catalog_delta.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.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 23, 2026

Copy link
Copy Markdown
Owner Author

Current HEAD: 644fd08e81940e1b124715835ac5b3ac6e0934d4

対応内容:

  • origin/main へ rebase し、catalog watch/Raft admin fields と migration wire fields の競合を解消しました。
  • Raw read-fence は RawGet/RawLatestCommitTS/RawScanAt/keys-only scan の stamped version と route bounds を維持し、LeaderRoutedStore の local leader 経路では nonzero read_route_version を fail-closed にしました。
  • 通常 routed scan/keys-only scan の proxy でも、stamped read_route_version と一緒に解決済み group_id を保持するようにしました。
  • Redis wide-column exact read/scan は logical route を優先し、upgrade 互換として legacy raw-key route を fallback/merge します。同一 key は logical route 優先で重複排除します。
  • Redis list auxiliary bare/cursor scans を logical routes へ fan-out し、route-bound filter は list delta/claim と stream meta/entry を logical user key で判定します。
  • catalog delta から in-memory engine へ migration fields / min_write_ts_exclusive を保持し、ShardStore write paths で route write timestamp floor を store.ErrWriteConflict として fail-closed にしました。
  • grouped reverse RawScanAt は read-fence fields が無い場合、read-fence-aware store でも explicit group reverse path を使うように戻しました。

Caller audit:

  • GetAtWithReadFence, LatestCommitTSWithReadFence, ScanAtWithReadFence, ScanKeysAtWithReadFence
  • getRouteAt (backup_scan.go は read-fence なしなので 0)
  • ApplyMutations*, PutAt, DeleteAt, PutWithTTLAt, ExpireAt, DeletePrefixAt*
  • routed scan proxy helpers and route-filter users

Validation:

  • make gen
  • git diff --check
  • go test ./distribution ./kv -count=1
  • go test ./adapter -run 'Test(Raw(Get|LatestCommitTS|ScanAt)|GRPCServer_RawScanAt|DistributionServer(ListRoutes|SplitRange|WatchCatalog|GetCatalogCapabilities)|GRPCCatalogWatcher|Redis.*(Wide|List|ZSet|Route|Fence)|Dynamo.*Migration)' -count=1
  • golangci-lint run ./distribution ./kv ./adapter --timeout=5m --allow-parallel-runners

@codex review

@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: 644fd08e81

ℹ️ 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_key.go
Comment thread kv/shard_store.go
Comment thread store/list_helpers.go Outdated
Comment on lines +178 to +179
userKeyLen := binary.BigEndian.Uint32(trimmed[:wideColKeyLenSize])
if uint32(len(trimmed)) < uint32(wideColKeyLenSize)+userKeyLen { //nolint:gosec // wideColKeyLenSize and encoded lengths fit in uint32

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 Validate list scan key lengths without uint32 wrap

If a caller supplies a malformed list delta/claim scan cursor whose encoded user-key length is near math.MaxUint32, the uint32(wideColKeyLenSize)+userKeyLen addition wraps, so the bounds check can pass even though the slice is too short; the subsequent slice on the next line then panics before the request can fail cleanly. This new scan-key parser is reachable from sharded scan routing for list auxiliary prefixes, so it should use a non-wrapping uint64/int length check like the stream helpers do.

Useful? React with 👍 / 👎.

Comment thread kv/shard_store.go
Comment thread adapter/distribution_server.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 (6c6bde4):

  • distribution/catalog.go
  • distribution/catalog_delta.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.go
  • distribution/grpc_watcher.go
  • distribution/grpc_watcher_test.go
  • 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 23, 2026

Copy link
Copy Markdown
Owner Author

Current HEAD: 6c6bde44ea1a9431ca4f74ce822bc937654fd43c

対応内容:

  • Catalog watch decode で route migration fields を保持するようにしました。
  • Redis wide-column bounded/pattern scan に legacy raw route を含め、logical route を優先するようにしました。
  • logical route に readTS 以下の version/tombstone がある場合は legacy fallback を止め、wide-column scan 結果も point-read で正規化して legacy row の復活を防ぎました。
  • list delta/claim scan key の長さ検証を wrap しない形にしました。

Caller audit:

  • GetAtWithReadFence / LatestCommitTSWithReadFence / latestCommitTSForRoute
  • ScanAtWithReadFence / ReverseScanAt / routesForRedisWideColumnScanWithVersion
  • routeDescriptorFromProto consumers (WatchCatalog, ListRoutes snapshot sync)
  • ExtractListUserKeyFromDelta* / ExtractListUserKeyFromClaim* routing callers
  • writeGroupForKey callers (PutAt, DeleteAt, TTL/expire, mutation batch, prefix delete)

Validation:

  • go test ./distribution ./store ./kv -count=1
  • go test ./adapter -run 'Test(DistributionServer(ListRoutes|SplitRange|CatalogWatch)|GRPCCatalogWatcher|GRPCServer_Raw(Get|LatestCommitTS|ScanAt)|RawKeyPairs)' -count=1
  • golangci-lint run ./distribution ./store ./kv ./adapter --timeout=5m --allow-parallel-runners
  • git diff --check

@codex review

@bootjp

bootjp commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Latest-head review threads were rechecked against 6c6bde4 and resolved after verifying the fixes are present:

  • route bounds are ignored unless route_bounds_present is true
  • explicit-group reverse scans still use the group path when they are not read-fenced
  • LeaderRoutedStore fails closed for local non-zero read_route_version fences
  • Redis wide-column point/scan reads include legacy raw-route compatibility while preferring logical-route data and tombstones
  • bare list auxiliary scans fan out through the route table
  • route MinWriteTSExclusive is enforced on write paths
  • catalog watcher preserves migration route fields

Validation:

  • go test ./adapter ./distribution ./kv -run 'Test(GRPCServer_RawScanAt_ReadFenceVariants|GRPCServer_RawScanAt_ReadFenceAwareStoreUsesExplicitGroupForNonFencedReverse|LeaderRoutedStore_RejectsLocalReadRouteVersion|LeaderRoutedStore_ProxiesReadFenceToLeader|LeaderRoutedStore_ForwardsKeyScanReadFenceWithoutValues|RouteDescriptorFromProtoPreservesMigrationFields|DistributionServer(ListRoutes|SplitRange|CatalogWatch)|ShardStoreWritePathsRejectRouteWriteTimestampFloor|ShardStoreScanAtWithReadFence_RoutesListAuxiliaryScansByUserKey|ShardStoreScanAtWithReadFence_FiltersRedisAuxiliaryBoundsByRouteKey|ShardStoreRoutesForWideColumnBoundedPatternIncludesLegacyRawRoute|ShardStoreRedisWideColumnReadsLegacyRawRoute|ShardStoreReverseRedisWideColumnScanPrefersLogicalRoute|ShardStoreScanAt_RoutesExactRedisWideColumnScanToOneShard|ShardStoreScanAt_RoutesRedisWideColumnCursorAcrossRemainingShards)' -count=1

@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: 6c6bde44ea

ℹ️ 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
Comment thread kv/shard_store.go
Comment thread kv/shard_store.go Outdated
}

func (s *ShardStore) ensurePrefixWriteAllowed(prefix []byte, commitTS uint64) error {
routes := s.engine.GetIntersectingRoutes(prefix, prefixScanEnd(prefix))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Route prefix deletes through logical key ranges

For raw internal prefixes such as the Redis FLUSHDB families (!lst|, !hs|, !st|, !zs|), this lookup checks the raw byte range instead of the logical user-key ranges those rows route by. A route fenced at, for example, Start: "m" is not inspected when deleting !hs|..., yet the subsequent delete still broadcasts tombstones to every group, so a commitTS <= MinWriteTSExclusive can be accepted for fenced logical keys.

Useful? React with 👍 / 👎.

Comment thread kv/shard_store.go Outdated
defer cancel()
cli := pb.NewRawKVClient(conn)
resp, err := cli.RawLatestCommitTS(ctx, &pb.RawLatestCommitTSRequest{Key: key})
resp, err := cli.RawLatestCommitTS(ctx, &pb.RawLatestCommitTSRequest{Key: key, ReadRouteVersion: readRouteVersion})

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 Keep latest probes route-specific

When the primary logical wide-column route is remote, this request still identifies only the key/version, so the leader answers RawLatestCommitTS with ShardStore.LatestCommitTSWithReadFence across both logical and legacy routes instead of just route.GroupID. If the logical route has a tombstone visible at the read timestamp but the legacy route has a newer future version, the fallback check does not stop and GetAt can return the older legacy value, resurrecting data that the logical tombstone should hide.

Useful? React with 👍 / 👎.

@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 (83ac727):

  • distribution/catalog.go
  • distribution/catalog_delta.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.go
  • distribution/grpc_watcher.go
  • distribution/grpc_watcher_test.go
  • 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 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Addressed the current wide-column migration read-fence findings in 83ac727:

  • RawLatestCommitTS now carries the selected group_id and the server answers explicit-group latest probes from that group only.
  • Redis hash/set/zset wide-column ScanAt and ScanKeysAt canonicalize each physical page through the logical route, so tombstoned legacy rows are skipped while pagination refills from later live rows.
  • Redis internal prefix deletes now preflight route MinWriteTSExclusive against the logical key ranges, including broad !redis| / !lst| / !hs| / !st| / !zs| families.

Validation:

  • make -C proto gen
  • go test ./kv ./adapter -run 'Test(ShardStoreRedisWideColumnScanRefillsAfterLogicalTombstones|ShardStoreDeletePrefixChecksRedisLogicalRouteFloors|ShardStore_ForwardsReadFenceStamps|GRPCServer_RawLatestCommitTS_UsesExplicitGroup|GRPCServer_RawReadFenceHelpersStampCurrentRouteVersion|GRPCServer_RawReadFenceHelpersKeepCallerRouteVersion)' -count=1\n- go test ./kv -run 'TestShardStore(.*WideColumn|.*Redis.*Prefix|.*ReadFence|.*ForwardsReadFence|DeletePrefixChecksRedisLogicalRouteFloors|ScanKeysRouteAtLeader)' -count=1\n- go test ./kv ./adapter -count=1 -timeout=10m\n- go test ./... -run '^$' -count=1 -timeout=10m\n- GOLANGCI_LINT_CACHE=$(pwd)/.golangci-cache golangci-lint --config=.golangci.yaml run ./adapter ./kv ./proto --timeout=5m --allow-parallel-runners\n- git diff --check HEAD~1..HEAD\n\nSemantic audit:\n- Checked DeletePrefixAt/DeletePrefixAtRaft/DeletePrefixAtRaftAt/DEL_PREFIX callers across adapter, kv, cmd, store, docs.\n- Checked LatestCommitTS/RawLatestCommitTS/proxyLatestCommitTS callers across adapter, kv, cmd, proto, store, docs.

@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: 83ac727755

ℹ️ 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
Comment thread kv/shard_store.go
Comment thread adapter/grpc.go
@bootjp

bootjp commented Jul 24, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Addressed current-head review blockers in b6ff276:

  • refill Redis wide-column keys-only and reverse scans after logical tombstone canonicalization drops physical legacy rows
  • enforce route MinWriteTSExclusive before ShardedCoordinator raw, txn, DEL_PREFIX, and TSO-stamped proposals reach Raft
  • keep route-bound explicit-group reverse RawScanAt valid against a real ShardStore
  • stabilize inline collection TTL coverage by issuing Redis writes against the current leader

Validation:

  • go test ./kv -run 'TestShardStoreRedisWideColumnScanRefillsAfterLogicalTombstones|TestShardStoreReverseRedisWideColumnScanRefillsAfterLogicalTombstones|TestShardStoreScanAtWithReadFence_AllowsExplicitGroupRouteBoundReverse|TestShardedCoordinatorDispatchNonTxn_RejectsRouteWriteTimestampFloor|TestShardedCoordinatorDispatchTxn_RejectsRouteWriteTimestampFloor|TestShardedCoordinator_DelPrefixRejectsRouteWriteTimestampFloor|TestShardedCoordinatorTSORawRejectsRouteWriteTimestampFloor' -count=1 -timeout=10m
  • go test ./adapter -run 'TestGRPCServer_RawScanAt_AllowsRouteBoundGroupedReverseWith(ReadFenceStore|ShardStore)|TestGRPCServer_RawScanAt_GroupedReverseStaysInvalidArgumentWithReadFenceStore|TestRedisCollectionExpireWritesInlineMetaTTL' -count=1 -timeout=10m
  • go test ./kv -count=1 -timeout=10m
  • go test ./adapter -count=1 -timeout=15m
  • golangci-lint --config=.golangci.yaml run ./kv ./adapter --timeout=5m --allow-parallel-runners
  • git diff --check

@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 (b6ff276):

  • distribution/catalog.go
  • distribution/catalog_delta.go
  • distribution/catalog_test.go
  • distribution/engine.go
  • distribution/engine_test.go
  • distribution/grpc_watcher.go
  • distribution/grpc_watcher_test.go
  • kv/sharded_coordinator.go
  • 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: b6ff276e13

ℹ️ 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 adapter/grpc.go
Comment on lines +318 to +320
if rawScanCanUseExplicitGroupReverse(req) {
if _, ok := r.store.(rawGroupReverseScanner); ok {
return r.rawScanAtExplicitGroup(ctx, req, req.GetGroupId(), limit, readTS)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve fenced handling for grouped reverse scans

When the backing store is a real ShardStore (it implements both rawGroupReverseScanner and rawReadFenceScanner), a RawScanAt request with group_id, reverse=true, and no route bounds takes this legacy explicit-group branch before the read-fence-aware path. That bypasses both the InvalidArgument rejection immediately below and server-side read_route_version stamping, so follower/proxy reverse scans can read an explicitly selected group without the migration fence that the value/key paths are trying to enforce. Apply the legacy shortcut only for stores that are not read-fence-aware, or let rawScanAtWithReadFence decide.

Useful? React with 👍 / 👎.

Comment thread kv/shard_store.go
Comment on lines +238 to +242
latest, exists, err := s.latestCommitTSForRoute(ctx, route, key, readRouteVersion)
if err != nil {
return false, err
}
return exists && latest <= ts, nil

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 Stop legacy fallback when older tombstones exist

For a non-leader primary route, this fallback probe only asks the leader for the latest commit timestamp; if the key has an older tombstone at or before ts and a later version after ts, latest > ts makes this return false and the code falls through to the legacy wide-column route. A snapshot read between those two timestamps can then resurrect the legacy value even though the primary route's tombstone should hide it. The remote probe needs to answer “any version at or before the read timestamp” rather than comparing only the newest commit timestamp.

Useful? React with 👍 / 👎.

Comment thread kv/sharded_coordinator.go
Comment on lines +2132 to +2136
muts := grouped[gid]
if ts != 0 {
if err := c.ensureMutationsWriteAllowed(muts, ts); err != nil {
return nil, err
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Enforce floors after forwarded TSO stamping

When c.tsAllocator is configured, rawLogTimestamp returns 0, so this branch skips MinWriteTSExclusive validation until leaseRefreshingTxn stamps the request. That works for local test/fake groups, but in a real follower path stampRawTimestampsForLocalCommit returns without stamping because the group engine is not leader, then Internal.Forward on the leader assigns r.Ts in adapter/internal.go and commits through a bare TransactionManager with no route-floor check. Non-transactional writes sent to a follower can therefore reach Raft at or below the route floor; the floor check needs to run on the forwarded stamping path too.

Useful? React with 👍 / 👎.

Comment thread kv/shard_store.go
Comment on lines +290 to +291
legacy, legacyVersion, ok := s.engine.GetRouteWithVersion(legacyKey)
version = max(version, legacyVersion)

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 Keep fallback routes in one catalog snapshot

This second route lookup can observe a newer catalog version than the primary route read just above, and the code then forwards both route choices using the max version. If a Redis wide-column key's primary route moves between the two GetRouteWithVersion calls, the request can carry the newer read_route_version while still explicitly reading the stale primary group, which defeats the fence on the leader after it waits for that version. Fetch the primary and legacy route candidates from a single engine snapshot or retry when the versions differ.

Useful? React with 👍 / 👎.

Comment thread kv/shard_key.go
Comment on lines +122 to +128
func normalizeRouteFilterKey(key []byte) []byte {
if user := redisListAuxiliaryRouteKey(key); user != nil {
return user
}
if user := redisStreamRouteKey(key); user != nil {
return user
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Route Redis auxiliary writes by user key

This makes route-bound scans classify list-delta/claim and stream rows by their logical Redis key, but write admission still calls routeKey, which does not apply these normalizers (stream keys remain under !stream|..., and list deltas are treated as the raw !lst|meta|d|... suffix). When a logical key in a moved or fenced route has one of these auxiliary writes, the write is checked against the raw-prefix route instead of the user-key route, so it can bypass MinWriteTSExclusive and later route-bound export/scans for the user interval can miss the row. Apply the same decoders to write routing/floor checks, or stop using them as route-bound ownership filters.

Useful? React with 👍 / 👎.

Comment thread kv/shard_store.go
Comment on lines +2828 to +2829
if scanned >= limit && !done {
return nil, errors.Wrapf(ErrTxnLocked, "scan lock budget exceeded for range [%q,%q)", string(start), string(end))

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 Don't count filtered-out locks against scan budget

For route-bound scans, this budget is incremented before the locks are filtered by routeKeyInScanBounds, so a page containing only locks for other logical routes can trip ErrTxnLocked as soon as scanned >= limit even though no relevant lock was found. A migrated-range scan over a raw Redis/list/stream prefix can therefore fail just because earlier keys in the same physical lock range belong to another route; the budget should be based on accepted route-matching locks or use a separate raw-scan cap large enough to page past unrelated locks.

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