test(integration): state-sync fixture — peer-floor fix, followers stop producing snapshots#487
Conversation
…p producing snapshots The state-sync suites' fixture stalled unconditionally: sei-tendermint's blocksync caught-up check has a hard >1-peer floor (pool.IsCaughtUp returns false for a single-peer node before any height math), and the fixture's first rpc follower had exactly one peer (the lone validator) at its WaitCaughtUp gate, so catching_up could never flip and both suites burned their scenario deadline inside provision. The fixture never had a green execution: the state-sync round-trip was proven manually on a multi-peer chain, and the single-validator fixture topology landed later on review + compile gates only, with no nightly cron to catch it. Two changes, both required: - provision brings rpc nodes up in two phases: create every node (each gains its siblings as blocksync peers), then gate each on caught-up + EVM serving. Gating node i before node i+1 exists strands a follower whose only peer is the validator. bringUpRPCNode splits into createRPCNode + gateRPCNode along the same phase line. - The fixture provisions two rpc followers (the sibling exists to be the second peer) and followers produce no snapshots (rpcConfig zeroes the interval): a light-client witness serves RPC trust points, chunks come from the snapshot-producing validator over p2p, and a producing follower at this chain's block rate requests snapshots faster than one takes to write, keeping a snapshot operation perpetually in progress. Root-caused live on harbor with blinded chain + infra lenses (environment falsified: disjoint nodes, no CPU limits, 10k-IOPS storage, co-tenant timeline exculpatory) and the peer floor confirmed at sei-tendermint internal/blocksync/pool.go:211-214 (present since 2023). Residual risk, empirically settled by the validation re-run: with snapshot drag removed and two fetch sources, follower apply must outrun ~15 blk/s production to reach head-1; the 60m scenario ctx bounds a miss. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR SummaryLow Risk Overview
The shared state-sync fixture ( Reviewed by Cursor Bugbot for commit d3bb76d. Bugbot is set up for automated code reviews on this repo. Configure here. |
Summary
The state-sync suites (TestWorkflowStateSync, TestGigaStoreMigration) stalled unconditionally in their shared fixture: sei-tendermint's blocksync caught-up check has a hard >1-peer floor (
pool.IsCaughtUpreturns false for a single-peer node before any height math,internal/blocksync/pool.go:211-214, present since 2023), and the fixture's first rpc follower had exactly one peer — the lone validator — at itsWaitCaughtUpgate.catching_upcould never flip; both suites burned their 60m scenario deadline insideprovision. The fixture never had a green execution: the state-sync round-trip was proven manually on a multi-peer chain, the single-validator topology landed later on review + compile gates only, and no nightly cron runs these suites.Two changes, both required:
provisionbrings rpc nodes up in two phases — create every node (createRPCNode: CreateNode + WaitReady), then gate each (gateRPCNode: WaitCaughtUp + WaitEVMServing). Gating node i before node i+1 exists strands a follower whose only peer is the validator.ErrConflictevery interval).Blast radius on the other suites sharing
provisionis nil: release/chaos/bench are 4-validator topologies (floor already cleared), genesis/upgrade have zero rpc nodes.Root cause
Root-caused live on harbor with blinded chain + infra lenses (/root-cause). Environment falsified by the assigned dissenter's own tests: workloads on disjoint nodes, no CPU limits, provisioned 10k-IOPS gp3, no chaos/netpol/pressure, and the co-tenant started 13 min after the stall began and completed while it persisted. Peer floor confirmed from source and live signals (n_peers=1; apply ≈14.5 blk/s vs produce ≈14.7 — a follower tracking seconds behind a bar it structurally cannot be credited with reaching).
Review
xreview ledger:
bdchatham-designs/designs/seinode-task/xreview/workflow-complete-at-release.mdRounds 10-11. First fix attempt (rpcNodes 1→2 alone) was caught broken by three independent blinded reviewers — provision's serial gate meant the second peer arrived too late — and repaired with the phase split. Round 11 unanimous RATIFY (sei-network-specialist as assigned dissenter, systems-engineer, idiomatic-reviewer).Two named empirical residuals, settled by the first live run (this fixture has never run green, so the run is the proof):
IsCaughtUpstill needs the follower to touchmaxPeerHeight-1against ~15 blk/s production. Snapshot-drag removal is the material lever;maxPeerHeightis a periodically-reported (slightly stale) bar. Moderate-to-good confidence; a timeout here means the apply-rate flake persists and needs a different lever.WaitReady's serve-probes clear pre-catch-up (they gate on liveness, notcatching_up—probe.go:46-48,83-85); a seid image that errorseth_blockNumberuntil synced would re-import the stall into the create loop.A validation run on harbor from the rebuilt harness image follows the merge.
🤖 Generated with Claude Code