Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
199 commits
Select commit Hold shift + click to select a range
43b4d73
store: add migration version import export
bootjp Jul 13, 2026
edf74ff
store: tighten migration export accounting
bootjp Jul 13, 2026
f95b557
distribution: add migration bracket planner
bootjp Jul 13, 2026
af847ef
Fix migration bracket edge cases
bootjp Jul 13, 2026
eab9622
Add migration fence drain guards
bootjp Jul 13, 2026
07a428e
Address migration guard review notes
bootjp Jul 13, 2026
7c17803
kv: fence broad mapped prefix deletes
bootjp Jul 13, 2026
2a85852
migration: add range version RPC handlers
bootjp Jul 13, 2026
fbd7f56
migration: raft-apply range imports
bootjp Jul 13, 2026
0fe341d
distribution: serve versioned ownership lookups
bootjp Jul 13, 2026
7d3b01c
migration: stage imported versions
bootjp Jul 13, 2026
e7f69ef
migration: merge staged visibility reads
bootjp Jul 13, 2026
b4f2477
migration: promote staged versions
bootjp Jul 13, 2026
2edefb8
migration: complete target promotion catalog state
bootjp Jul 13, 2026
2ea0d38
migration: add target readiness guard
bootjp Jul 13, 2026
b93f5b9
distribution: add split job management RPCs
bootjp Jul 13, 2026
c1afe27
store: persist promote applied index
bootjp Jul 13, 2026
ca1a050
migration: harden staged route writes
bootjp Jul 13, 2026
58c2128
distribution: page split job listing
bootjp Jul 13, 2026
e3079c0
store: fix migration export blockers
bootjp Jul 13, 2026
dd52db8
Gate migration promotion replay safety
bootjp Jul 13, 2026
5ba3e82
kv: enforce target readiness guards
bootjp Jul 13, 2026
b04d30f
store: keep promote replay ungated
bootjp Jul 13, 2026
a2ee041
Guard target readiness apply paths
bootjp Jul 13, 2026
643a5a6
store: fix migration export metadata handling
bootjp Jul 13, 2026
6ac85a1
Fix target readiness guard gaps
bootjp Jul 13, 2026
ce91b66
Guard manifest scan readiness routes
bootjp Jul 13, 2026
d33bf35
Harden staged migration visibility
bootjp Jul 13, 2026
f2bcd65
Fix target readiness route proofs
bootjp Jul 13, 2026
7cc0875
Merge cross-group migration base
bootjp Jul 13, 2026
f727f30
Enable split migration job creation
bootjp Jul 13, 2026
c72eace
Validate promote cursor before proposal
bootjp Jul 13, 2026
53d38e3
Harden split migration readiness checks
bootjp Jul 13, 2026
a624a21
Harden target readiness route proofs
bootjp Jul 13, 2026
fa769ac
Harden split migration start guards
bootjp Jul 13, 2026
4b8e345
Harden staged visibility OCC guards
bootjp Jul 13, 2026
4447dd3
Reject non-active migration sources
bootjp Jul 13, 2026
061275a
Bound migration export sparse scans
bootjp Jul 13, 2026
b5723b5
Fix target readiness staged delete paths
bootjp Jul 13, 2026
ca503cf
Fix staged migration read safety
bootjp Jul 13, 2026
f22c4ff
Stabilize urgent compactor pagination test
bootjp Jul 13, 2026
31ed507
Fix migration export metadata handling
bootjp Jul 13, 2026
2065650
Fix migration route bracket filtering
bootjp Jul 13, 2026
119dda2
Guard staged readiness probes
bootjp Jul 13, 2026
2b50129
Fix staged migration guard gaps
bootjp Jul 14, 2026
9f0b7f1
store: skip export writer registry rows
bootjp Jul 14, 2026
e6f88bd
Guard target readiness retry paths
bootjp Jul 14, 2026
83a3d99
Merge cross-group migration base
bootjp Jul 14, 2026
79b3409
Tighten target readiness proof
bootjp Jul 14, 2026
ce0c2e1
Wire split migration capability gate
bootjp Jul 14, 2026
f884ed2
Replicate target readiness guards
bootjp Jul 14, 2026
3cb3aad
store: advance promotion commit watermark
bootjp Jul 14, 2026
c5dae8f
Fix bounded store export edge cases
bootjp Jul 14, 2026
49adab3
Gate split migration on peer capability
bootjp Jul 14, 2026
c459255
Fix migration route edge cases
bootjp Jul 14, 2026
c64ff5f
migration: harden split capability gate
bootjp Jul 14, 2026
90fa654
store: honor raft promotion sync mode
bootjp Jul 14, 2026
a775fda
Trim Lua negative cache bound test
bootjp Jul 14, 2026
2b2cbd2
store: harden Pebble migration export
bootjp Jul 14, 2026
a9c9afe
Trim Lua negative cache bound test
bootjp Jul 14, 2026
67f3e9d
store: separate list delta key prefix
bootjp Jul 14, 2026
eebdbf2
Stabilize stream latency seed writes
bootjp Jul 14, 2026
c298060
Enable split migration capability gate
bootjp Jul 14, 2026
05b72cf
Bound migration export scan skips
bootjp Jul 14, 2026
5280996
Fix migration routing edge cases
bootjp Jul 14, 2026
a653226
Fence routed migration exports
bootjp Jul 14, 2026
e7467d5
Route legacy list deltas and stream scans
bootjp Jul 14, 2026
70fb630
Keep split migration capability fail closed
bootjp Jul 14, 2026
aa94570
Add migration bracket planner (#1086)
bootjp Jul 14, 2026
aff2a9f
migration: enable split migration job creation (#1093)
bootjp Jul 14, 2026
9f8dab7
Merge remote-tracking branch 'origin/design/hotspot-split-m2-wire' in…
bootjp Jul 14, 2026
6892dd9
Skip txn locks in migration export
bootjp Jul 14, 2026
fba7560
Filter legacy list deltas by value
bootjp Jul 14, 2026
9f80fa9
migration: tighten readiness guard publication
bootjp Jul 14, 2026
ccda608
migration: merge m2 wire and fix legacy deltas
bootjp Jul 14, 2026
585e5ac
Merge remote-tracking branch 'origin/design/hotspot-split-m2-store-ex…
bootjp Jul 14, 2026
727c1dd
Merge remote-tracking branch 'origin/design/hotspot-split-m2-fence-dr…
bootjp Jul 14, 2026
5acb33f
migration: fence S3 bucket metadata writes
bootjp Jul 14, 2026
db7a325
Merge remote-tracking branch 'origin/design/hotspot-split-m2-fence-dr…
bootjp Jul 14, 2026
14aa9e9
migration: guard read-only shard validation
bootjp Jul 14, 2026
5254a43
Merge cross-group migration base
bootjp Jul 14, 2026
295cdf6
migration: close cross-group floor gaps
bootjp Jul 14, 2026
b1381f3
migration: validate promotion resume state
bootjp Jul 14, 2026
dddda07
migration: validate staged readiness conflicts
bootjp Jul 14, 2026
84704f9
Close legacy list export gaps
bootjp Jul 14, 2026
650c450
migration: route staged s3 auxiliaries
bootjp Jul 14, 2026
b4b8664
Merge cross-group migration fixes
bootjp Jul 14, 2026
19a28e9
kv: keep floor checks out of raft replay
bootjp Jul 14, 2026
40c2f52
store: ignore stale promotion cursors
bootjp Jul 14, 2026
327cb1c
Merge remote-tracking branch 'origin/design/hotspot-split-m2-cross-gr…
bootjp Jul 14, 2026
f1aeeeb
Guard split fence retry paths
bootjp Jul 14, 2026
1db42a8
Merge remote-tracking branch 'origin/design/hotspot-split-m2-fence-dr…
bootjp Jul 14, 2026
4b1d950
Merge remote-tracking branch 'origin/design/hotspot-split-m2-cross-gr…
bootjp Jul 14, 2026
961a177
Merge remote-tracking branch 'origin/design/hotspot-split-m2-promote'…
bootjp Jul 14, 2026
9d9e051
Fix promotion completion merge compatibility
bootjp Jul 14, 2026
8e74d6e
Merge promotion completion into target readiness
bootjp Jul 14, 2026
2d57ae9
Fail closed read-only shard readiness checks
bootjp Jul 14, 2026
9994ec7
Merge remote-tracking branch 'origin/design/hotspot-split-m2-target-r…
bootjp Jul 14, 2026
8d11161
Guard snapshot spooling disk headroom
bootjp Jul 14, 2026
0215c38
Raise snapshot spool headroom reserve
bootjp Jul 14, 2026
774779b
Fix raft startup and snapshot spool guards
bootjp Jul 14, 2026
46722f6
Handle route fences in adapter retries
bootjp Jul 14, 2026
70cf6f8
Stabilize raft snapshot dispatch and maintenance gates
bootjp Jul 14, 2026
a241809
Honor partition resolver in fence prechecks
bootjp Jul 14, 2026
ee363c4
Make raft startup and fence checks deterministic
bootjp Jul 14, 2026
54ad999
Gate public startup after raft replay
bootjp Jul 14, 2026
e20475f
Stabilize raft dispatch and S3 cleanup fences
bootjp Jul 14, 2026
c3a8ecf
Stabilize raft startup and write fences
bootjp Jul 14, 2026
61feed4
Stabilize route-fence cleanup retries
bootjp Jul 14, 2026
f373cd3
Keep heartbeat responses coalescing under read-index load
bootjp Jul 14, 2026
8f821fe
Stabilize raft snapshot recovery checkpoints
bootjp Jul 14, 2026
3e988ef
Enforce current route fences at apply time
bootjp Jul 14, 2026
04e8053
Prioritize received raft snapshots
bootjp Jul 14, 2026
d818602
Stabilize snapshot catch-up and fence checks
bootjp Jul 14, 2026
db9843a
Stabilize startup reads and snapshot recovery
bootjp Jul 15, 2026
a6d7d76
Reset stale raft peer connections
bootjp Jul 15, 2026
c8f865e
Stabilize snapshot catch-up and fence routing
bootjp Jul 15, 2026
b553090
Keep SQS receive route fences visible
bootjp Jul 15, 2026
d2b22ac
Stabilize redis proxy and raft recovery
bootjp Jul 15, 2026
549a786
Add migration fence drain guards (#1087)
bootjp Jul 15, 2026
fefd809
Fix sparse Lua list pop fallback
bootjp Jul 16, 2026
e1b32b5
Align ElasticKV proxy socket timeouts
bootjp Jul 16, 2026
cf47858
Replay blocking zset pops deterministically
bootjp Jul 16, 2026
f697640
Cap ElasticKV secondary script concurrency
bootjp Jul 16, 2026
7e40979
Refresh ElasticKV leader after not-leader replies
bootjp Jul 16, 2026
3df9239
Avoid full stream rewrites for Lua XADD
bootjp Jul 16, 2026
d19b2a4
Handle Redis proxy replay edge cases
bootjp Jul 16, 2026
a850ee1
distribution: add split job management RPCs (#1092)
bootjp Jul 16, 2026
b8bb6ad
Honor Lua XADD cached state
bootjp Jul 16, 2026
adf5cdb
Cover Lua XADD maxlen zero append
bootjp Jul 16, 2026
01b02ad
Merge remote-tracking branch 'origin/main' into work/pr1088-conflict
bootjp Jul 16, 2026
f02d1c0
Merge remote-tracking branch 'origin/design/hotspot-split-m2-store-ex…
bootjp Jul 16, 2026
7407423
Enforce migration write floors during apply
bootjp Jul 16, 2026
2c920bc
Fence migration exports with applied reads
bootjp Jul 16, 2026
bdf05a6
Delete staged rows for migrated prefixes
bootjp Jul 16, 2026
c9d7ddc
Preserve staged scan visibility
bootjp Jul 16, 2026
bbc1876
migration: harden target readiness guards
bootjp Jul 16, 2026
a02b6c1
migration: add target readiness guard (#1091)
bootjp Jul 16, 2026
acc9305
migration: fix staged s3 bucket routing
bootjp Jul 16, 2026
f902f34
migration: persist promotion timestamp floor
bootjp Jul 16, 2026
e3e37ce
migration: keep invalid promote cursors non-halting
bootjp Jul 16, 2026
f6457de
migration: promote staged versions (#1089)
bootjp Jul 16, 2026
a3b7276
Merge remote-tracking branch 'origin/design/hotspot-split-m2-cross-gr…
bootjp Jul 16, 2026
f51ca32
Merge remote-tracking branch 'origin/design/hotspot-split-m2-promotio…
bootjp Jul 16, 2026
5dec8cb
migration: fix promotion complete review findings
bootjp Jul 16, 2026
00da46c
migration: make promotion completion retry idempotent
bootjp Jul 16, 2026
19961d3
migration: disambiguate legacy list exports
bootjp Jul 16, 2026
bd55701
store: preserve empty-key migration exports
bootjp Jul 16, 2026
8a687ca
migration: tighten routed cleanup safety
bootjp Jul 16, 2026
fd179f9
migration: preserve ambiguous list tombstones
bootjp Jul 16, 2026
c275022
adapter: preserve scan route groups for list cleanup
bootjp Jul 16, 2026
5cf01fd
adapter: backtrack list compactor accepted tails
bootjp Jul 16, 2026
7fe4112
kv: cover pinned primary transaction commits
bootjp Jul 16, 2026
83cd5bf
ci: generate redis proxy image metadata locally
bootjp Jul 16, 2026
0e76181
proxy: allow redis-only without secondary seeds
bootjp Jul 16, 2026
ab82447
ci: avoid failing lint on reviewdog API errors
bootjp Jul 16, 2026
5189172
ci: keep lint required when reviewdog is unavailable
bootjp Jul 16, 2026
319b442
migration: persist applied index on imports
bootjp Jul 16, 2026
2c29191
kv: preserve broad scans with staged routes
bootjp Jul 16, 2026
aaa96da
migration: gate import proposals during rollouts
bootjp Jul 17, 2026
d34d103
kv: reject raw prefix writes below floors
bootjp Jul 17, 2026
78a0400
migration: route partitioned exports by group
bootjp Jul 17, 2026
4851c6f
kv: scan staged routes for physical limits
bootjp Jul 17, 2026
052c64c
Merge cross-group migration fixes
bootjp Jul 17, 2026
2b7c3af
migration: keep split capability gated
bootjp Jul 17, 2026
eea5dec
adapter: pin sparse list fallback route bounds
bootjp Jul 17, 2026
1b70e39
redis: fix Lua XADD and blocking move replay
bootjp Jul 17, 2026
8df8acf
proxy: replay blocking multipop writes
bootjp Jul 17, 2026
9a0286d
proxy: avoid retrying user not-leader errors
bootjp Jul 17, 2026
7b12482
proxy: classify not-leader redis replies safely
bootjp Jul 17, 2026
5d78d7a
migration: reject armed readiness without write floor
bootjp Jul 17, 2026
178fda6
docs: mark hotspot m2 migration partial
bootjp Jul 17, 2026
c065ad9
migration: run split target promotion
bootjp Jul 17, 2026
252bd64
migration: harden split runner promotion
bootjp Jul 17, 2026
938a284
distribution: keep split migration gates closed
bootjp Jul 17, 2026
3e1c85f
Fix sparse Lua list pop fallback (#1094)
bootjp Jul 17, 2026
1c7ea5b
distribution: finish split promotion cleanup
bootjp Jul 17, 2026
07c4eea
Merge hotspot split M2 wire updates
bootjp Jul 18, 2026
3a7c3c2
Fix pinned migration cleanup routing
bootjp Jul 18, 2026
903e589
adapter: preserve stream metadata on Lua expiry
bootjp Jul 18, 2026
b3a3e7e
Merge remote-tracking branch 'origin/design/hotspot-split-m2-wire' in…
bootjp Jul 18, 2026
2c3d7d8
Merge remote-tracking branch 'origin/design/hotspot-split-m2-store-ex…
bootjp Jul 18, 2026
79405da
Merge remote-tracking branch 'origin/design/hotspot-split-m2-store-ex…
bootjp Jul 18, 2026
d9da086
raft: report cold-start replay gaps safely
bootjp Jul 18, 2026
5affdac
Merge remote-tracking branch 'origin/design/hotspot-split-m2-store-ex…
bootjp Jul 18, 2026
34706b0
Merge remote-tracking branch 'origin/design/hotspot-split-m2-cross-gr…
bootjp Jul 18, 2026
df4370b
Merge remote-tracking branch 'origin/design/hotspot-split-m2-promotio…
bootjp Jul 18, 2026
7c1f0aa
distribution: timestamp completed split jobs
bootjp Jul 18, 2026
737b930
kv: preserve migration fence bypasses
bootjp Jul 18, 2026
7cc8008
Merge hotspot split promotion updates
bootjp Jul 18, 2026
0c74b60
Complete split migration runner phases
bootjp Jul 18, 2026
634a75e
Complete hotspot split M2 migration lifecycle
bootjp Jul 18, 2026
1cbee6a
Track post-arm two-phase commits during split
bootjp Jul 18, 2026
8264ea3
Close split migration startup and retry gaps
bootjp Jul 18, 2026
28449f9
Complete hotspot split M2 migration lifecycle (#1096)
bootjp Jul 19, 2026
db933c0
docs: mark hotspot split M2 implemented
bootjp Jul 19, 2026
f270d8d
docs: link implemented hotspot split design
bootjp Jul 19, 2026
19c2657
Resolving merge conflicts with base branch
Copilot Jul 20, 2026
6b54f22
docs: resolve merge conflicts with base branch
Copilot Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions docs/design/2026_02_18_partial_hotspot_shard_split.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,12 +293,13 @@ Add RPCs:
2. Job phases: BACKFILL/FENCE/DELTA/CUTOVER
3. Manual split with target-group relocation

Status: partial. SplitJob catalog/codec, MVCC export/import primitives, staged
visibility, write-fence checks, target readiness, and target-promotion catalog
components exist in the M2 stack, but no production runner advances cross-group
jobs to `DONE` yet. M2 remains open in
[`2026_06_11_partial_hotspot_split_milestone2_migration.md`](2026_06_11_partial_hotspot_split_milestone2_migration.md)
until the cross-group acceptance criteria and Jepsen workload pass.
Status: implemented. The production runner advances durable cross-group jobs
through BACKFILL, FENCE, DELTA_COPY, CUTOVER, CLEANUP, and `DONE`; current-voter
readiness and cleanup barriers protect leadership changes; and the deterministic
Jepsen workload covers the split alongside leader-kill and partition packages.
The completed M2 contract is recorded in
[`2026_06_11_implemented_hotspot_split_milestone2_migration.md`](2026_06_11_implemented_hotspot_split_milestone2_migration.md)
and its final runner/lifecycle slice landed in PR #1096.

### Milestone 3: Automation

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Hotspot Shard Split — Milestone 2: Migration Plane

Status: Partial
Status: Implemented
Author: bootjp
Date: 2026-06-11

Parent: [2026_02_18_partial_hotspot_shard_split.md](2026_02_18_partial_hotspot_shard_split.md).
M1 (control plane) is as-built in [2026_02_18_implemented_hotspot_split_milestone1_pr.md](2026_02_18_implemented_hotspot_split_milestone1_pr.md).

Current implementation status: partial. The SplitJob catalog/codec, versioned route descriptor storage, range export/import primitives, staged-read visibility, write-fence checks, target readiness, and target-promotion catalog pieces have landed or are covered by the active M2 stack. The feature is not implemented end to end until a production runner advances cross-group jobs to `DONE`, `ListRoutes` exposes the moved child on its target group after cutover, and the Jepsen cross-group split workload passes the acceptance criteria in §13.
Current implementation status: implemented. The M2 stack provides the durable SplitJob catalog, versioned route descriptors, resumable range export/import, staged/live visibility, source write and read fences, current-voter readiness and cleanup barriers, constant-time route cutover, incremental target promotion, bounded source/target cleanup, terminal `DONE` history, and the deterministic cross-group Jepsen workload. PR #1096 completed the production runner and lifecycle wiring. Automatic hotspot detection and split scheduling remain M3 scope; the broader route-shuffle and fault campaign remains M4 scope.

## 1. Background

Expand Down Expand Up @@ -1243,7 +1243,7 @@ Phased into reviewable PRs, each lands behind its own doc-or-test gate:
| M2-PR5 | Coordinator + FSM FENCE rejection (`ErrRouteWriteFenced`) with point and `DEL_PREFIX` range-footprint checks + route-faithful txn-lock drain (§3.2a.0a) + same-group `SplitRange` overlap rejection while a SplitJob is live | fsm + coordinator unit + `migrator_lock_drain_test` + `catalog_test` overlap red controls |
| M2-PR6 | Cross-group end-to-end: ExportRangeVersions / ImportVersions server-side handlers + migrator BACKFILL/DELTA_COPY + raw-candidate staged/live merge read path in both scan directions and `LatestCommitTS` + §7.2.2e source-side cutover read-fence arm with every-current-source-voter ACK, membership-epoch re-ACK, catalog-version waiter, route-key-normalized scan ownership checks, and server-stamped RawKV read versions | integration incl. delete/TTL DELTA_COPY, Redis list/hash/set/zset/stream migration, HLC restart/fence-floor cases + `kv/fsm_cutover_read_fence_test.go` |
| M2-PR7 | Target-local `PromotionState` + background promoter + ordered default-group promotion-complete CAS retaining `min_write_ts_exclusive` + source/target cleanup before DONE history move; readiness guard accepts matching cleared descriptors while retained; `AbandonSplitJob` with durable `ABANDONING` cleanup witness + CLEANUP GC + Jepsen split workload | `kv/fsm_promote_staged_test.go` raw hidden-version/LatestCommitTS merge + jepsen suite |
| M2-PR8 | Rename `*_proposed_*` → `*_partial_*` after PR1 ships; update parent partial doc M2 status; rename to `*_implemented_*` after PR7 | |
| M2-PR8 | Rename `*_proposed_*` → `*_partial_*` after PR1 ships; update parent partial doc M2 status; rename to `*_implemented_*` after PR7 | Completed after the runner, voter barriers, cleanup lifecycle, route publication, and Jepsen workload landed in PR #1096. |

Each PR follows the five-lens self-review and is gated by its tests + `make lint`.

Expand Down Expand Up @@ -1283,9 +1283,12 @@ This is independent of the existing rolling-upgrade protocol for unrelated subsy

## 14. Lifecycle

This document is `*_partial_*` because M2-PR1 and later component slices have landed, but the cross-group migration plane is not complete end to end.
This document is `*_implemented_*` because the M2 cross-group migration plane is complete as a central subsystem. The production runner now resumes durable jobs across leadership changes, drives every phase through `CLEANUP`, waits for current source and target voter proofs, publishes the target route, removes bounded migration state, and moves the job to `DONE` history. The deterministic Jepsen split workload exercises the cross-group operation alongside leader-kill and partition fault packages.

- Track per-PR landing under §11.
- Rename to `*_implemented_*` only after the acceptance criteria in §13 pass: cross-group `StartSplitMigration` reaches `phase=DONE`, `ListRoutes` shows the target-group child after cutover, leader-kill recovery is automatic, and the Jepsen split workload is green.
The remaining work is intentionally outside M2's central scope:

- M3 owns automatic hotspot detection, target selection, and split scheduling.
- M4 owns the broader route-shuffle nemesis matrix and production-scale fault campaigns.
- Reverse migration after CUTOVER and concurrent migration jobs remain future extensions.

`git mv` is used so history follows.
8 changes: 4 additions & 4 deletions docs/design/2026_06_12_proposed_scaling_roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,9 @@ control-plane (`*_proposed_*` doc TBD).**

- M1 standalone but doesn't enable cross-region writes — it just
makes Raft survive cross-WAN partition.
- M2 depends on the M2 hotspot-split migration contract
(`2026_06_11_partial_hotspot_split_milestone2_migration.md`)
being implemented so the monotone-merge primitive exists.
- M2's hotspot-split migration dependency is implemented in
[2026_06_11_implemented_hotspot_split_milestone2_migration.md](2026_06_11_implemented_hotspot_split_milestone2_migration.md), including
the monotone-merge primitive.
Comment thread
bootjp marked this conversation as resolved.
- M3 depends on M1's region-aware membership and M2's per-region
ceiling.
- M4 depends on M2 and M3.
Expand Down Expand Up @@ -538,7 +538,7 @@ the ceiling shape:
Composability invariant: **every monotone-merge happens via the
same `SetPhysicalCeiling` + `Observe` primitive**. The M2
hotspot-split contract (§6.2.1 of
`2026_06_11_partial_hotspot_split_milestone2_migration.md`) is the
[2026_06_11_implemented_hotspot_split_milestone2_migration.md](2026_06_11_implemented_hotspot_split_milestone2_migration.md)) is the
reference implementation; per-region and per-group merges reuse it.
Comment thread
bootjp marked this conversation as resolved.

### 7.2 Capability bits
Expand Down
8 changes: 4 additions & 4 deletions docs/design/2026_06_23_proposed_scaling_roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ memory each group's private cache/memtable pins.

- **Range split — distribute a range across groups.** Same-group split
shipped in M1 (`distribution/`). Cross-group migration (the part that
actually relocates data and reduces per-node volume) is tracked by **PR #945**
and the active M2 stack
(`docs/design/2026_06_11_partial_hotspot_split_milestone2_migration.md`,
branch `docs/hotspot-split-m2-proposal`): a resumable `SplitJob` with
actually relocates data and reduces per-node volume) is implemented by the
M2 stack recorded in
[2026_06_11_implemented_hotspot_split_milestone2_migration.md](2026_06_11_implemented_hotspot_split_milestone2_migration.md):
a resumable `SplitJob` with
Comment thread
bootjp marked this conversation as resolved.
`PLANNED → BACKFILL → FENCE → DELTA_COPY → CUTOVER → CLEANUP → DONE` phases
driven by a migrator on the default-group leader. M2 is the required
ownership-migration mechanism, but it reduces per-node bytes only when the
Expand Down
43 changes: 35 additions & 8 deletions main_encryption_registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,19 @@ func retryUntilRegistered(ctx context.Context, what string, fn func() error) err
func setupDistributionAndRegistration(
runCtx context.Context,
eg *errgroup.Group,
runtimes []*raftGroupRuntime,
distCatalog *distribution.CatalogStore,
engine *distribution.Engine,
coordinate *kv.ShardedCoordinator,
defaultGroup *kv.ShardGroup,
w encryptionWriteWiring,
raftID string,
sidecarPath string,
) (*distribution.CatalogStore, error) {
) error {
if err := validateRaftRegistrationStartupEpoch(defaultGroup, w, raftID, sidecarPath); err != nil {
return nil, err
return err
}
if err := installProcessStartRegistrationGate(runCtx, eg, coordinate, defaultGroup, w, raftID); err != nil {
return nil, err
return err
}
installRaftRegistrationVerifier(defaultGroup, w, raftID)
installRuntimeRaftRegistrationWatcher(runCtx, eg, coordinate, defaultGroup, w, raftID, sidecarPath)
Expand All @@ -153,11 +153,38 @@ func setupDistributionAndRegistration(
installRuntimeRegistrationWatcher(runCtx, eg, coordinate, defaultGroup, w, raftID)
// Bootstrap + registration both run under runCtx so a shutdown
// cancels the bounded retry rather than hanging.
distCatalog, err := setupDistributionCatalog(runCtx, runtimes, engine)
if err != nil {
return nil, err
return ensureDistributionCatalogSnapshot(runCtx, distCatalog, engine)
}

func ensureDistributionCatalogSnapshot(
ctx context.Context,
distCatalog *distribution.CatalogStore,
engine *distribution.Engine,
) error {
if distCatalog == nil {
return errors.New("distribution catalog store is not available")
}
// EnsureCatalogSnapshot may Save through the direct (non-raft) write
// path. When the §7.1 storage envelope is active and this load's
// writer registration has not yet committed, that Save fails closed
// with store.ErrWriterNotRegistered (Stage 7a-2). retryUntilRegistered
// retries the bootstrap until the registration goroutine — armed
// before this call in setupDistributionAndRegistration — commits and
// the gate clears. The common cases (populated catalog → no-op Save,
// or pre-cutover → cleartext Save) never hit the gate and return on
// the first attempt.
//
// Idempotency requirement: the retry re-invokes EnsureCatalogSnapshot
// from scratch on each ErrWriterNotRegistered, so it MUST be
// re-entrant — on the populated-catalog path it is a version-unchanged
// no-op Save (no mutation, no nonce), so re-running it is safe.
if err := retryUntilRegistered(ctx, "distribution catalog bootstrap", func() error {
_, e := distribution.EnsureCatalogSnapshot(ctx, distCatalog, engine)
return errors.Wrap(e, "ensure catalog snapshot")
}); err != nil {
return errors.Wrapf(err, "initialize distribution catalog")
}
return distCatalog, nil
return nil
}

func installRaftRegistrationVerifier(defaultGroup *kv.ShardGroup, w encryptionWriteWiring, raftID string) {
Expand Down
Loading