Skip to content

tso: route durable timestamps through group leader#1108

Merged
bootjp merged 1 commit into
design/dedicated-tso-fsmfrom
design/dedicated-tso-leader-routing
Jul 19, 2026
Merged

tso: route durable timestamps through group leader#1108
bootjp merged 1 commit into
design/dedicated-tso-fsmfrom
design/dedicated-tso-leader-routing

Conversation

@bootjp

@bootjp bootjp commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • route dedicated group-0 timestamp requests to the current TSO leader
  • commit every returned window end and fence each leader term above authoritative data-group commit floors
  • add synchronous fail-closed shadow migration and a durable one-way cutover marker
  • preserve rolling compatibility by rejecting legacy timestamp responses without durable reservation metadata
  • update the centralized TSO design status through M6

Migration safety

  • shadow candidates are serialized through group 0 before the legacy value is returned
  • overlapping legacy candidates are discarded and retried
  • cutover commits the marker before the first production window
  • group-0, shadow, and cutover failures stop timestamp issuance instead of falling back

Validation

  • go test ./kv -count=1 -timeout=10m
  • go test . -count=1 -timeout=10m
  • go test ./adapter -run 'Test(DistributionServerGetTimestamp|GRPCServer_RawLatestCommitTS_EmptyKeyReturnsGlobalWatermark)' -count=1 -timeout=5m
  • go test ./... -run '^$' -count=1 -timeout=10m
  • go test -race ./kv -run 'Test(RaftTSOAllocator|LeaderRoutedTSOAllocator|ShadowTimestampAllocator|ShardStoreGlobalCommittedTimestampFloor)' -count=1 -timeout=10m
  • golangci-lint --config=.golangci.yaml run ./kv ./adapter . --timeout=5m
  • make gen BREAKING_AGAINST='../.git#subdir=proto,branch=design/dedicated-tso-runtime'

Stack

Base: #1103

Author: bootjp

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4d1a31e2-133f-4933-9aa2-d7bca2031c61

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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 (3147271):

  • kv/sharded_coordinator.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 commented Jul 18, 2026

Copy link
Copy Markdown
Owner Author

Latest head: 3147271e5b8db7d4a6f61773b022a46113627fc9

Implemented and locally verified:

  • durable group-0 window commits and strict per-term data-group commit-floor fencing
  • follower-to-leader gRPC routing with legacy protocol rejection
  • synchronous fail-closed shadow serialization and overlap retry
  • one-way cutover marker committed before the first production window
  • snapshot compatibility and cutover marker restore validation
  • caller audit for direct HLC issuance and adapter timestamp helpers

Local validation passed:

  • full ./kv tests
  • full root package tests
  • targeted Distribution/RawLatestCommitTS adapter tests
  • compile-only ./...
  • targeted race tests
  • golangci-lint
  • proto breaking/generation against the stacked base

@codex review

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request implements a centralized Timestamp Oracle (TSO) by introducing a dedicated Raft group 0, a minimal TSOStateMachine, and allocators (RaftTSOAllocator, LeaderRoutedTSOAllocator, and ShadowTimestampAllocator) to manage durable timestamp windows and serialize legacy HLC candidates during migration. Key feedback on these changes highlights critical issues, including an uninitialized connCache in LeaderRoutedTSOAllocator that leads to a nil pointer dereference, a performance bottleneck caused by holding a mutex across blocking network and Raft operations, a race condition between Raft proposal commits and FSM application in commitCutover, sequential latency bottlenecks when querying data-group commit floors, and a bug where wrapped errors prevent status.Code from extracting the correct gRPC status codes.

Important

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

Comment thread kv/tso_raft.go
Comment on lines +275 to +299
func NewLeaderRoutedTSOAllocator(
local TSOAllocator,
leader raftengine.LeaderView,
opts ...LeaderRoutedTSOAllocatorOption,
) (*LeaderRoutedTSOAllocator, error) {
if local == nil {
return nil, errors.WithStack(ErrTSOAllocatorRequired)
}
if leader == nil {
return nil, errors.WithStack(ErrTSOGroupRequired)
}
a := &LeaderRoutedTSOAllocator{
local: local,
leader: leader,
retryBudget: defaultTSORouteRetryBudget,
retryInterval: defaultTSORouteRetryInterval,
}
for _, opt := range opts {
if opt != nil {
opt(a)
}
}
a.remoteRequest = a.requestRemoteBatch
return a, nil
}

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.

critical

The connCache field of LeaderRoutedTSOAllocator is never initialized or populated in NewLeaderRoutedTSOAllocator. Since GRPCConnCache is an interface, calling a.connCache.ConnFor(addr) in requestRemoteBatch will result in a nil pointer dereference panic in production. Consider adding a WithGRPCConnCache option or passing the connection cache to the constructor so it can be properly wired.

Comment thread kv/tso_raft.go
Comment on lines +135 to +138
a.mu.Lock()
defer a.mu.Unlock()
return a.reserveBatchAfterLocked(ctx, n, min, activateCutover)
}

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.

high

Holding the mutex a.mu across the entire reserveBatchAfterLocked call is a severe performance bottleneck. This method performs sequential network gRPC calls (GlobalCommittedTimestampFloor via termCommitFloor) and blocking Raft proposals (commitCutover and commitAllocationFloor). Because these blocking operations are executed under the lock, all concurrent TSO allocation requests on this node will experience head-of-line blocking, limiting the TSO throughput to a fraction of its potential. Consider initializing the term floor outside the hot-path lock (e.g., using a double-checked locking pattern or a separate coordination state) and minimizing the duration the lock is held.

Comment thread kv/tso_raft.go
Comment on lines +222 to +234
func (a *RaftTSOAllocator) commitCutover(ctx context.Context, engine raftengine.Engine) error {
if _, err := a.group.Proposer().Propose(ctx, marshalTSOCutover()); err != nil {
wrapped := errors.Wrap(err, "tso commit cutover marker")
if tsoProposalLostLeadership(engine, err) {
return stderrors.Join(ErrTSONotLeader, wrapped)
}
return wrapped
}
if !a.state.CutoverActive() {
return errors.New("tso cutover proposal committed without applied marker")
}
return nil
}

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.

high

There is a race condition in commitCutover between the Raft proposal commit and the FSM apply. Propose blocks until the entry is committed to the Raft log, but the FSM Apply runs asynchronously on the Raft apply loop. Immediately after Propose returns, a.state.CutoverActive() is highly likely to still be false in production, causing the cutover to spuriously fail with "tso cutover proposal committed without applied marker". Consider removing this strict synchronous assertion, or waiting for the FSM to apply the entry before returning.

Comment thread kv/shard_store.go
Comment on lines +1385 to +1395
var maxTS uint64
for _, groupID := range ids {
ts, err := s.authoritativeGroupLastCommitTS(ctx, groupID, s.groups[groupID])
if err != nil {
return 0, errors.Wrapf(err, "tso commit floor: group %d", groupID)
}
if ts > maxTS {
maxTS = ts
}
}
return maxTS, nil

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.

medium

GlobalCommittedTimestampFloor queries every data group sequentially to find the maximum commit timestamp. To avoid sequential latency bottlenecks, execute these checks concurrently (e.g., using an errgroup.Group) while optimizing with a fast path for the single-group case to avoid concurrency overhead.

References
  1. When performing lease or freshness checks on multiple keys in a sharded or distributed system, deduplicate the keys by their owning shard or Raft group first to minimize network round-trips. If multiple groups are involved, execute the checks concurrently to avoid sequential latency bottlenecks, while optimizing with a fast path for the single-group case to avoid concurrency overhead.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

対応しました。data group が1つのときは従来どおり直列fast path、複数のときは上限16でerrgroup並列照会し、いずれかのleader fence失敗時は全体をfail-closedにします。2つのRPCが双方開始するまで解放しないbarrier testをrace付きで追加しました。HEAD: df46968

Comment on lines +225 to 241
func timestampRPCError(err error) error {
if code := status.Code(err); code != codes.Unknown {
return err
}
switch {
case errors.Is(err, context.Canceled):
return errors.WithStack(status.Error(codes.Canceled, err.Error()))
case errors.Is(err, context.DeadlineExceeded):
return errors.WithStack(status.Error(codes.DeadlineExceeded, err.Error()))
case errors.Is(err, kv.ErrInvalidTSOBatchSize), errors.Is(err, kv.ErrTxnCommitTSRequired):
return errors.WithStack(status.Error(codes.InvalidArgument, err.Error()))
case errors.Is(err, kv.ErrTSONotLeader), errors.Is(err, kv.ErrLeaderNotFound):
return errors.WithStack(status.Error(codes.FailedPrecondition, err.Error()))
default:
return errors.WithStack(status.Error(codes.Unavailable, err.Error()))
}
}

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.

medium

status.Code(err) is called directly on err, which may be wrapped using cockroachdb/errors (e.g., errors.Wrap or errors.WithStack). Wrapped errors do not expose the gRPC status code directly to status.Code, causing them to return codes.Unknown. This will make all wrapped gRPC errors fall through to the default case and return codes.Unavailable instead of preserving their original gRPC status code. Consider unwrapping the error using errors.Cause(err) or errors.UnwrapAll(err) before extracting the status code.

@bootjp

bootjp commented Jul 18, 2026

Copy link
Copy Markdown
Owner Author

TLA CI の失敗は実装ではなく、TLA Tools v1.8.0 の配布 jar が更新され checksum が変わったことが原因でした。Makefile の固定 SHA-256 を現在の配布物に更新し、make tla-tools && make tla-check で safe model 全件成功・gap model 全件期待どおり失敗を確認しました。

最新 HEAD: ff83dd644c647e5a6325b67073cc47049d5b622d

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

  • kv/sharded_coordinator.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 18, 2026

Copy link
Copy Markdown
Owner Author

Proto CI が最新 main の既存 RawScanAtRequest.keys_only = 7 を削除した差分として判定していたため、stacked branch に同じ後方互換 field と再生成済み Go binding を取り込みました。

検証:

  • make gen(main に対する buf breaking を含む)
  • go test ./proto ./adapter -run TestDistributionServerGetTimestamp -count=1 -timeout=5m

最新 HEAD: 211466338927e6293a4ba8339a1397ab76ae1a0f

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

  • kv/sharded_coordinator.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.

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

  • kv/sharded_coordinator.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 18, 2026

Copy link
Copy Markdown
Owner Author

data-group commit floor の直列照会を改善しました。単一groupはfast path、複数groupは上限16で並列化し、どのgroupのauthoritative leader fenceにも到達できなければ従来どおりfail-closedです。

検証:

  • go test -race ./kv -run TestShardStoreGlobalCommittedTimestampFloor -count=1 -timeout=5m
  • go test ./kv -count=1 -timeout=10m
  • golangci-lint --config=.golangci.yaml run ./kv --timeout=5m

最新 HEAD: df4696893a4a50f31fa728dece0787a70a9cd4a4

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

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

@bootjp

bootjp commented Jul 18, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: df4696893a

ℹ️ 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
}
requestCtx, cancel := context.WithTimeout(nonNilTSOContext(ctx), proxyForwardTimeout)
defer cancel()
resp, err := pb.NewRawKVClient(conn).RawLatestCommitTS(requestCtx, &pb.RawLatestCommitTSRequest{})

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 Require a leader fence for remote floor reads

When the local ReadIndex path fails or Leader() is stale, this empty-key RawLatestCommitTS call can still succeed against a deposed/non-leader endpoint: the server-side empty-key handler just returns store.LastCommitTS() and does not verify leadership for the target data group. In that leader-churn case the TSO term can accept a stale follower watermark instead of failing closed, so it may initialize below a commit that already exists on the new data-group leader.

Useful? React with 👍 / 👎.

@bootjp bootjp Jul 18, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in d4444e7 and retained in latest HEAD 8927523. Remote floor requests now carry the explicit group ID; the receiving ShardStore.GroupCommittedTimestampFloor requires local leadership and completes a linearizable ReadIndex before returning that group watermark. Targeted follower-rejection and leader-success tests pass with race enabled.

Comment thread proto/service.proto
uint64 ts = 4; // optional read timestamp; if zero, server uses current HLC
bool reverse = 5;
uint64 group_id = 6; // optional explicit Raft group for non-range-owned keyspaces
bool keys_only = 7; // when true, response kv entries omit values

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 keys_only in RawScanAt responses

This new wire flag advertises that values are omitted when keys_only is true, but the RawKV server never reads GetKeysOnly() and adapter/grpc.go still always serializes each RawKVPair.Value via rawKvPairs. Any client relying on this option for a keys-only scan will still receive full values, which defeats the API contract and can unnecessarily expose or transfer large payloads.

Useful? React with 👍 / 👎.

@bootjp bootjp Jul 18, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in latest HEAD 8927523. RawScanAt now honors keys_only: it uses key-only store/group scan interfaces when available and otherwise strips values before building the response, including reverse and explicit-group compatibility paths. Added race-tested coverage for the explicit-group optimized path and the fallback path; both assert empty response values.

Comment thread main.go Outdated
Comment on lines +1726 to +1727
if !*tsoEnabled && !*tsoShadowEnabled {
return wiring, 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.

P1 Badge Honor durable TSO cutover without mode flags

If a node restarts after another node has durably set the group-0 cutover marker but comes up with both --tsoEnabled and --tsoShadowEnabled false, this early return leaves the coordinator on the legacy HLC path and never pins timestamp issuance to group 0. That can reintroduce non-serialized legacy timestamps after cutover, undermining the one-way marker that is supposed to prevent mixed timestamp sources during restarts or partial rollouts.

Useful? React with 👍 / 👎.

@bootjp bootjp Jul 18, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in latest HEAD 8927523. Startup now reads the restored group-0 cutover marker before mode selection. A durable marker forces production group-0 routing even when both flags are false or only shadow mode is requested, so restart cannot return to legacy issuance. Regression tests pre-commit the marker, reset proposal counts, reconfigure, and prove only the allocation-floor proposal occurs.

@bootjp

bootjp commented Jul 18, 2026

Copy link
Copy Markdown
Owner Author

自己監査で、remote data-group floor が接続先groupを明示せず、RPC到着時のleadershipを再検証していない経路を修正しました。RawLatestCommitTSRequest.group_id を追加し、受信nodeで対象groupのlocal leadershipとlinearizable ReadIndexを確認した後だけ、そのgroupのwatermarkを返します。旧leader・follower・group不在はfail-closedです。既存callerはgroup_id=0の従来動作を維持し、TSO term-floor callerだけが新契約を使います。

検証:

  • make gen
  • go test -race ./kv ./adapter -run 'Test(ShardStore(GlobalCommittedTimestampFloor|GroupCommittedTimestampFloor)|GRPCServer_RawLatestCommitTS)' -count=1 -timeout=5m\n- golangci-lint --config=.golangci.yaml run ./kv ./adapter --timeout=5m\n- go test ./... -run '^$' -count=1 -timeout=10m\n\n最新 HEAD: d4444e72c54a79159ed439164806d3c2ff2e97aa\n\n@codex review

@github-actions

Copy link
Copy Markdown
Contributor

TLA+ spec divergence review (auto-triggered)

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

Anchored files changed in this PR head (d4444e7):

  • kv/sharded_coordinator.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: d4444e72c5

ℹ️ 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 proto/service.proto
uint64 ts = 4; // optional read timestamp; if zero, server uses current HLC
bool reverse = 5;
uint64 group_id = 6; // optional explicit Raft group for non-range-owned keyspaces
bool keys_only = 7; // when true, response kv entries omit values

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 keys_only in RawScanAt responses

When a client sets this new keys_only option, the advertised contract says values are omitted, but RawScanAt never reads req.GetKeysOnly() and always builds the response through adapter/grpc.go:200 -> rawKvPairs, which copies each Value unconditionally at adapter/grpc.go:236-239. Any caller using the new option still receives full values, so large or sensitive scans pay the full transfer cost and violate the API contract.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 8927523. RawScanAt now honors keys_only for explicit-group optimized scanners and the compatibility fallback. The fallback strips values before returning, and adapter regression tests cover both paths.

Comment thread kv/shard_store.go
return 0, errors.Wrapf(ErrTSOCommitFloorUnavailable,
"read data group %d leader %s watermark: %v", groupID, addr, err)
}
return resp.GetTs(), 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.

P1 Badge Reject legacy watermark replies

During a rolling upgrade where the data-group leader still runs a binary that predates RawLatestCommitTSRequest.group_id, protobuf drops the unknown group_id and the old handler treats this as the empty-key request, returning a node-global LastCommitTS without the new group-specific leadership/ReadIndex fence. Since this caller accepts any successful response here, TSO term initialization can be satisfied by the legacy path instead of failing closed, so the floor may be stale or for the wrong group.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in ccc2916. Explicit-group watermark responses now echo group_id and set leader_fenced only after the group ReadIndex fence succeeds. The TSO floor client rejects a missing marker or mismatched group as both protocol-unsupported and floor-unavailable. Legacy-response and wrong-group regression tests cover the rolling-upgrade case.

Comment thread kv/tso_raft.go Outdated
if err != nil {
return empty, err
}
previousFloor := max(a.state.AllocationFloor(), termFloor)

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 Revalidate the TSO term before returning a window

If this goroutine loses group-0 leadership while termCommitFloor or the cutover proposal is in flight and later regains leadership before commitAllocationFloor, the cached term/floor from this point is still used to allocate from the local HLC. A different leader may already have committed and returned a higher allocation floor; because TSO floor entries apply with storeMaxUint64, this node can commit a lower floor entry successfully and return a window overlapping that prior leader's window. Re-check the current term/floor after the blocking steps, or reject on term change, before exposing the reservation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in ccc2916. The allocator revalidates the same group-0 term with a fresh leader fence after floor/cutover work, then checks the term again after the allocation floor commits and before returning the window. A term change drops the committed window; a retry starts above its durable floor. Regression tests cover changes during floor discovery and immediately after proposal apply.

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

  • kv/sharded_coordinator.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 18, 2026

Copy link
Copy Markdown
Owner Author

Latest head: 8927523

Resolved the current-head review findings:

  • remote data-group floors are group-specific and leader-fenced
  • RawScanAt honors keys_only, with optimized interfaces where available and value omission on compatibility fallback
  • a restored durable cutover marker overrides absent or shadow startup flags and forces production group-0 routing

Validation passed:

  • race tests for all ConfigureCoordinatorTSO cases
  • race tests for RawScanAt and RawLatestCommitTS
  • full root and kv package tests
  • compile-only all packages
  • golangci-lint for root and adapter
  • caller audit for TSO configuration and every RawScanAtRequest construction

An additional package-wide adapter run reached its existing 10-minute multi-node integration timeout; the changed adapter tests pass under race and GitHub CI is rerunning.

@codex review
@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

@bootjp I’ll review the latest changes at 8927523101b209d01e9d8667a011c7f28f9720c8, including the group-fenced floor lookup, keys_only behavior, and durable cutover restoration paths.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 8927523101

ℹ️ 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".

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

  • kv/sharded_coordinator.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 18, 2026

Copy link
Copy Markdown
Owner Author

@codex review
@coderabbitai review

Latest head ccc2916 addresses the remaining current findings:

  • explicit-group watermark responses echo the requested group and carry a leader-fenced protocol marker; old or mismatched responses fail closed
  • the allocator revalidates the same group-0 term after floor/cutover work and again after committing the allocation floor, dropping any window across a term change
  • keys-only explicit-group scans remain covered from 8927523

Verification:

  • go test -race ./kv -run Test(RaftTSOAllocator|ShardStoreGlobalCommittedTimestampFloor) -count=1
  • go test -race ./adapter -run TestGRPCServer_RawLatestCommitTS -count=1
  • go test ./kv -count=1
  • go test ./... -run ^$ -count=1
  • golangci-lint --config=.golangci.yaml run ./kv ./adapter . --timeout=5m
  • make -C proto gen
  • git diff --check

Caller audit covered every RawLatestCommitTS request/response path, both commit-floor entrypoints, and all RaftTSOAllocator construction/reservation call sites.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

@bootjp I’ll review the latest changes, focusing on the explicit-group leader-fence protocol, group-0 term revalidation around allocation commits, and the existing keys_only coverage.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: ccc291672d

ℹ️ 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 main.go
Comment on lines +1734 to +1736
if *tsoEnabled {
routedOpts = append(routedOpts, kv.WithTSOCutoverActivation())
}

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 Require cutover confirmation after restored marker

When this node has restored the one-way cutover marker but is restarted without --tsoEnabled, this leaves routed.activate false even though the coordinator is put into production TSO mode below. In the follower case, requestRemoteBatch only rejects cutover_active=false responses when activate is true, so a stale or mismatched TSO leader response can be accepted after local cutover restore without confirming the leader also fenced the cutover marker. Include cutoverActive in this condition so restored-cutover nodes continue to fail closed on non-cutover responses.

Useful? React with 👍 / 👎.

Comment thread kv/tso_fsm.go Outdated
Comment thread main.go
if err != nil {
return wiring, errors.Wrap(err, "configure dedicated tso allocator")
}
wiring.serverAllocator = local

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 Gate remote cutover on local TSO/shadow mode

Because serverAllocator is populated before the no-mode early return, a group-0 leader started with neither --tsoEnabled nor --tsoShadowEnabled will still accept a follower's activate_cutover RPC through Distribution.GetTimestamp, commit the durable cutover marker, and then keep using its legacy local coordinator until restart. In that partial rollout, local writes from the leader can continue issuing unshadowed legacy timestamps after cutover has become durable; either avoid exporting the allocator in this mode or reject activation unless the local process is already in shadow/TSO mode.

Useful? React with 👍 / 👎.

Base automatically changed from design/dedicated-tso-runtime to design/dedicated-tso-fsm July 19, 2026 06:08
@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 (93b8633):

  • kv/sharded_coordinator.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/dedicated-tso-fsm branch from e701cb2 to 97a42ba Compare July 19, 2026 12:17
@bootjp
bootjp force-pushed the design/dedicated-tso-leader-routing branch from 93b8633 to 295b851 Compare July 19, 2026 12:32
@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 (295b851):

  • kv/sharded_coordinator.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 19, 2026

Copy link
Copy Markdown
Owner Author

Evidence for current HEAD 295b85152fdd88a9765e1eafae2e7c142e9397e8:

  • Rebased onto tso: add dedicated ceiling fsm #1095 HEAD 97a42ba72c18205fcb84a43ad4ca0cedc48efa31 and rebuilt as one PR-visible commit.
  • Allocation-floor and one-way cutover entries now use distinct versioned TSO envelopes. Both retain the old data-FSM fail-closed prefix; bare encryption-reserved bytes cannot mutate TSO state.
  • Caller audit covered direct NextTimestamp, Clock().Next, NextFenced, floor/cutover proposal encoders, routed allocator construction, and restored-cutover activation. Remaining direct HLC issuance is confined to the documented pre-cutover compatibility/shadow paths; production and restored cutover route through group 0.
  • TLA audit matched every safe and expected-gap outcome.
  • PR-visible author and committer are bootjp <contact@bootjp.me>; GitHub signature verification is verified: true.
  • Final tree: b782b89b9c9b85d4c0e3b61e6e83b0fce3071222.

Validation:

  • go test ./kv -count=1
  • go test . -run "TestConfigureCoordinatorTSO|TestBuildShardGroupsWithDedicatedTSO|TestGroupDataDir|TestEncryptionAdmin_" -count=1
  • go test ./adapter -run "TestDistributionServerGetTimestamp|TestRawLatestCommitTS" -count=1
  • go test -race ./kv -run "Test(RaftTSOAllocator|LeaderRoutedTSOAllocator|ShadowTimestampAllocator|TSOStateMachine)" -count=1
  • golangci-lint run ./... --timeout=5m --allow-parallel-runners (0 issues)
  • make gen
  • make tla-check
  • git diff --check origin/design/dedicated-tso-fsm..HEAD

Current-root inline findings were zero before the base rebuild. Requesting a fresh latest-head review now.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 295b85152f

ℹ️ About Codex in GitHub

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

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

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

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

bootjp commented Jul 19, 2026

Copy link
Copy Markdown
Owner Author

Current HEAD 295b85152fdd88a9765e1eafae2e7c142e9397e8 remains mergeable with every required check successful and zero current-root inline findings. The prior evidence comment covers the sanitized one-commit history, fail-closed versioned envelopes, caller audit, TLA outcomes, tests, lint, and verified bootjp signature. Requesting the missing latest-head review result.

@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: 295b85152f

ℹ️ 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 main.go
@bootjp
bootjp force-pushed the design/dedicated-tso-leader-routing branch from 295b851 to 9182f37 Compare July 19, 2026 13:59
@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 (9182f37):

  • kv/sharded_coordinator.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 commented Jul 19, 2026

Copy link
Copy Markdown
Owner Author

Evidence for current HEAD 9182f378f75401617f38cfae9d80b92305c10c1b:

  • Fixed the startup-gate timestamp source gap: startupGatedCoordinator exposes the inner allocator through TimestampAllocatorProvider, and internalTimestampOptions resolves that provider before constructing every Internal.Forward service.
  • Follower-forwarded raw writes with Ts=0 are now stamped by the same dedicated group-0 batch allocator used by the coordinator. A legacy coordinator still installs no allocator option and preserves the fenced HLC fallback.
  • Semantic caller audit covered ShardedCoordinator.rawLogTimestamp, Internal.nextTimestamp, startServersAfterStartupRotation, every internalTimestampOptions use, and all TimestampAllocatorThrough callers.
  • The PR remains one commit on the sanitized tso: add dedicated ceiling fsm #1095 base. GitHub reports bootjp contact@bootjp.me for author and committer with a valid verified signature.

Verification:

  • focused root and kv tests for startup-gate wiring, TSO mode configuration, timestamp allocation, and follower deferral
  • focused race tests for the same paths
  • full golangci-lint: 0 issues
  • make tla-check: every safe/liveness model passed and every gap model failed with its expected invariant
  • go test ./...: every completed package passed; the local adapter suite exceeded its 15-minute suite timeout under concurrent worktree load, so the clean-runner full CI result is being treated as the required gate

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 9182f378f7

ℹ️ About Codex in GitHub

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

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

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

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

@bootjp
bootjp merged commit aa94f4e into design/dedicated-tso-fsm Jul 19, 2026
11 checks passed
@bootjp
bootjp deleted the design/dedicated-tso-leader-routing branch July 19, 2026 14:18
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