feat: backfill 等待/跳过守卫 — 适配 Codex 26.609,PR3#18
Merged
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Wangnov
force-pushed
the
feat/multi-store-write
branch
from
June 13, 2026 05:56
078dd5f to
bb50bfa
Compare
Wangnov
force-pushed
the
feat/multi-store-backfill-guard
branch
from
June 13, 2026 05:58
2aa959e to
7e18e57
Compare
Wangnov
added a commit
that referenced
this pull request
Jun 13, 2026
PR4 of the multi-store adaptation (builds on #18). `watch` now maintains every discovered store, not just one, by sharing the multi-store write path. - Extract reconcile_stores_core(.., backup, ..) used by both the one-shot backed-up path (reconcile_all_stores_with_backup) and a new no-backup reconcile_all_stores for the continuous watch service. - The core supports the incremental MismatchedRows scope with an AllRows rollout followup (when rows change), matching the former single-store watch path. - backup=false skips per-store backups AND the rollout change journal, so watch does not litter backups/ every poll (matching the old reconcile_once, which passed no journal path). - watch passes Duration::ZERO as the backfill wait: a store mid-backfill is skipped this poll and retried next, never blocking the loop. With a rollout-rewriting scope, PR3's whole-round skip means watch quietly waits out a backfill and resumes when it completes. - Remove the now-unused single-store path: reconcile_once, ReconcileSummary, print_sync_summary, add_rollout_summary. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the no-backup path still wrote a rollout change journal (a regression vs the old watch); fixed by gating the journal on backup, with a regression test asserting the watch path writes no backups/rollouts.*.jsonl. 54 tests, clippy and fmt clean.
Wangnov
force-pushed
the
feat/multi-store-write
branch
from
June 13, 2026 06:11
bb50bfa to
abcee40
Compare
Wangnov
force-pushed
the
feat/multi-store-backfill-guard
branch
from
June 13, 2026 06:12
7e18e57 to
030fd33
Compare
Wangnov
added a commit
that referenced
this pull request
Jun 13, 2026
PR4 of the multi-store adaptation (builds on #18). `watch` now maintains every discovered store, not just one, by sharing the multi-store write path. - Extract reconcile_stores_core(.., backup, ..) used by both the one-shot backed-up path (reconcile_all_stores_with_backup) and a new no-backup reconcile_all_stores for the continuous watch service. - The core supports the incremental MismatchedRows scope with an AllRows rollout followup (when rows change), matching the former single-store watch path. - backup=false skips per-store backups AND the rollout change journal, so watch does not litter backups/ every poll (matching the old reconcile_once, which passed no journal path). - watch passes Duration::ZERO as the backfill wait: a store mid-backfill is skipped this poll and retried next, never blocking the loop. With a rollout-rewriting scope, PR3's whole-round skip means watch quietly waits out a backfill and resumes when it completes. - Remove the now-unused single-store path: reconcile_once, ReconcileSummary, print_sync_summary, add_rollout_summary. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the no-backup path still wrote a rollout change journal (a regression vs the old watch); fixed by gating the journal on backup, with a regression test asserting the watch path writes no backups/rollouts.*.jsonl. 54 tests, clippy and fmt clean.
Wangnov
added a commit
that referenced
this pull request
Jun 13, 2026
PR4 of the multi-store adaptation (builds on #18). `watch` now maintains every discovered store, not just one, by sharing the multi-store write path. - Extract reconcile_stores_core(.., backup, ..) used by both the one-shot backed-up path (reconcile_all_stores_with_backup) and a new no-backup reconcile_all_stores for the continuous watch service. - The core supports the incremental MismatchedRows scope with an AllRows rollout followup (when rows change), matching the former single-store watch path. - backup=false skips per-store backups AND the rollout change journal, so watch does not litter backups/ every poll (matching the old reconcile_once, which passed no journal path). - watch passes Duration::ZERO as the backfill wait: a store mid-backfill is skipped this poll and retried next, never blocking the loop. With a rollout-rewriting scope, PR3's whole-round skip means watch quietly waits out a backfill and resumes when it completes. - Remove the now-unused single-store path: reconcile_once, ReconcileSummary, print_sync_summary, add_rollout_summary. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the no-backup path still wrote a rollout change journal (a regression vs the old watch); fixed by gating the journal on backup, with a regression test asserting the watch path writes no backups/rollouts.*.jsonl. 54 tests, clippy and fmt clean.
Wangnov
force-pushed
the
feat/multi-store-write
branch
from
June 13, 2026 06:34
abcee40 to
fcffc5e
Compare
Wangnov
force-pushed
the
feat/multi-store-backfill-guard
branch
from
June 13, 2026 06:34
030fd33 to
61940f9
Compare
Wangnov
added a commit
that referenced
this pull request
Jun 13, 2026
PR4 of the multi-store adaptation (builds on #18). `watch` now maintains every discovered store, not just one, by sharing the multi-store write path. - Extract reconcile_stores_core(.., backup, ..) used by both the one-shot backed-up path (reconcile_all_stores_with_backup) and a new no-backup reconcile_all_stores for the continuous watch service. - The core supports the incremental MismatchedRows scope with an AllRows rollout followup (when rows change), matching the former single-store watch path. - backup=false skips per-store backups AND the rollout change journal, so watch does not litter backups/ every poll (matching the old reconcile_once, which passed no journal path). - watch passes Duration::ZERO as the backfill wait: a store mid-backfill is skipped this poll and retried next, never blocking the loop. With a rollout-rewriting scope, PR3's whole-round skip means watch quietly waits out a backfill and resumes when it completes. - Remove the now-unused single-store path: reconcile_once, ReconcileSummary, print_sync_summary, add_rollout_summary. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the no-backup path still wrote a rollout change journal (a regression vs the old watch); fixed by gating the journal on backup, with a regression test asserting the watch path writes no backups/rollouts.*.jsonl. 54 tests, clippy and fmt clean.
Wangnov
force-pushed
the
feat/multi-store-write
branch
from
June 13, 2026 06:44
fcffc5e to
64f5c8c
Compare
Wangnov
force-pushed
the
feat/multi-store-backfill-guard
branch
from
June 13, 2026 06:45
61940f9 to
5d6cce5
Compare
Wangnov
added a commit
that referenced
this pull request
Jun 13, 2026
PR4 of the multi-store adaptation (builds on #18). `watch` now maintains every discovered store, not just one, by sharing the multi-store write path. - Extract reconcile_stores_core(.., backup, ..) used by both the one-shot backed-up path (reconcile_all_stores_with_backup) and a new no-backup reconcile_all_stores for the continuous watch service. - The core supports the incremental MismatchedRows scope with an AllRows rollout followup (when rows change), matching the former single-store watch path. - backup=false skips per-store backups AND the rollout change journal, so watch does not litter backups/ every poll (matching the old reconcile_once, which passed no journal path). - watch passes Duration::ZERO as the backfill wait: a store mid-backfill is skipped this poll and retried next, never blocking the loop. With a rollout-rewriting scope, PR3's whole-round skip means watch quietly waits out a backfill and resumes when it completes. - Remove the now-unused single-store path: reconcile_once, ReconcileSummary, print_sync_summary, add_rollout_summary. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the no-backup path still wrote a rollout change journal (a regression vs the old watch); fixed by gating the journal on backup, with a regression test asserting the watch path writes no backups/rollouts.*.jsonl. 54 tests, clippy and fmt clean.
Wangnov
force-pushed
the
feat/multi-store-write
branch
from
June 13, 2026 06:58
64f5c8c to
268baf2
Compare
PR3 of the multi-store adaptation (builds on #17). Before writing, the multi-store path now waits (bounded) for each store's Codex startup-backfill to finish, so threadripper never races Codex's rebuild. - wait_for_store_backfill polls backfill_state (read-only): no table or a `complete` status is ready immediately; otherwise it waits up to backfill_wait (default 10s) and then reports the store busy. - A busy store is reported StoreOutcome::Skipped, and neither its rollout targets nor its DB are touched. - Because rewriting the shared rollout JSONL would race a running backfill's reads (the rollout files are its source of truth), a rollout-rewriting scope (AllRows) combined with any in-progress backfill skips the whole round; --sqlite-only (RolloutScope::None) still writes its ready stores. - main returns Partial(2) / Failed(1) accordingly; the --sqlite-only App warning now fires only when the App store was actually updated. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the first cut still rewrote the shared rollout JSONL (racing the backfill) even while skipping busy stores' DBs; fixed with the whole-round skip above, plus a regression test asserting that a shared rollout and both DBs stay untouched while a backfill runs. 53 tests, clippy and fmt clean.
Wangnov
force-pushed
the
feat/multi-store-backfill-guard
branch
from
June 13, 2026 06:59
5d6cce5 to
20e1a7e
Compare
Wangnov
added a commit
that referenced
this pull request
Jun 13, 2026
PR4 of the multi-store adaptation (builds on #18). `watch` now maintains every discovered store, not just one, by sharing the multi-store write path. - Extract reconcile_stores_core(.., backup, ..) used by both the one-shot backed-up path (reconcile_all_stores_with_backup) and a new no-backup reconcile_all_stores for the continuous watch service. - The core supports the incremental MismatchedRows scope with an AllRows rollout followup (when rows change), matching the former single-store watch path. - backup=false skips per-store backups AND the rollout change journal, so watch does not litter backups/ every poll (matching the old reconcile_once, which passed no journal path). - watch passes Duration::ZERO as the backfill wait: a store mid-backfill is skipped this poll and retried next, never blocking the loop. With a rollout-rewriting scope, PR3's whole-round skip means watch quietly waits out a backfill and resumes when it completes. - Remove the now-unused single-store path: reconcile_once, ReconcileSummary, print_sync_summary, add_rollout_summary. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the no-backup path still wrote a rollout change journal (a regression vs the old watch); fixed by gating the journal on backup, with a regression test asserting the watch path writes no backups/rollouts.*.jsonl. 54 tests, clippy and fmt clean.
Wangnov
added a commit
that referenced
this pull request
Jun 13, 2026
PR4 of the multi-store adaptation (builds on #18). `watch` now maintains every discovered store, not just one, by sharing the multi-store write path. - Extract reconcile_stores_core(.., backup, ..) used by both the one-shot backed-up path (reconcile_all_stores_with_backup) and a new no-backup reconcile_all_stores for the continuous watch service. - The core supports the incremental MismatchedRows scope with an AllRows rollout followup (when rows change), matching the former single-store watch path. - backup=false skips per-store backups AND the rollout change journal, so watch does not litter backups/ every poll (matching the old reconcile_once, which passed no journal path). - watch passes Duration::ZERO as the backfill wait: a store mid-backfill is skipped this poll and retried next, never blocking the loop. With a rollout-rewriting scope, PR3's whole-round skip means watch quietly waits out a backfill and resumes when it completes. - Remove the now-unused single-store path: reconcile_once, ReconcileSummary, print_sync_summary, add_rollout_summary. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the no-backup path still wrote a rollout change journal (a regression vs the old watch); fixed by gating the journal on backup, with a regression test asserting the watch path writes no backups/rollouts.*.jsonl. 54 tests, clippy and fmt clean.
Wangnov
added a commit
that referenced
this pull request
Jun 13, 2026
PR4 of the multi-store adaptation (builds on #18). `watch` now maintains every discovered store, not just one, by sharing the multi-store write path. - Extract reconcile_stores_core(.., backup, ..) used by both the one-shot backed-up path (reconcile_all_stores_with_backup) and a new no-backup reconcile_all_stores for the continuous watch service. - The core supports the incremental MismatchedRows scope with an AllRows rollout followup (when rows change), matching the former single-store watch path. - backup=false skips per-store backups AND the rollout change journal, so watch does not litter backups/ every poll (matching the old reconcile_once, which passed no journal path). - watch passes Duration::ZERO as the backfill wait: a store mid-backfill is skipped this poll and retried next, never blocking the loop. With a rollout-rewriting scope, PR3's whole-round skip means watch quietly waits out a backfill and resumes when it completes. - Remove the now-unused single-store path: reconcile_once, ReconcileSummary, print_sync_summary, add_rollout_summary. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the no-backup path still wrote a rollout change journal (a regression vs the old watch); fixed by gating the journal on backup, with a regression test asserting the watch path writes no backups/rollouts.*.jsonl. 54 tests, clippy and fmt clean.
Wangnov
added a commit
that referenced
this pull request
Jun 13, 2026
PR4 of the multi-store adaptation (builds on #18). `watch` now maintains every discovered store, not just one, by sharing the multi-store write path. - Extract reconcile_stores_core(.., backup, ..) used by both the one-shot backed-up path (reconcile_all_stores_with_backup) and a new no-backup reconcile_all_stores for the continuous watch service. - The core supports the incremental MismatchedRows scope with an AllRows rollout followup (when rows change), matching the former single-store watch path. - backup=false skips per-store backups AND the rollout change journal, so watch does not litter backups/ every poll (matching the old reconcile_once, which passed no journal path). - watch passes Duration::ZERO as the backfill wait: a store mid-backfill is skipped this poll and retried next, never blocking the loop. With a rollout-rewriting scope, PR3's whole-round skip means watch quietly waits out a backfill and resumes when it completes. - Remove the now-unused single-store path: reconcile_once, ReconcileSummary, print_sync_summary, add_rollout_summary. Reviewed in parallel by Codex and a Claude subagent. Codex caught that the no-backup path still wrote a rollout change journal (a regression vs the old watch); fixed by gating the journal on backup, with a regression test asserting the watch path writes no backups/rollouts.*.jsonl. 54 tests, clippy and fmt clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
PR1(#16,只读发现+多库 status)、PR2(#17,
sync/bucket switch写路径多库化)。Codex 26.609 启动时会跑一次 backfill(从 rollout 重建 state DB),进度记在backfill_state表(running/complete)。PR3 给多库写路径加 backfill 等待/跳过守卫,避免与重建竞态。共识见 #14。改动
wait_for_store_backfill(db, budget):只读轮询backfill_state.status。无表(老 Codex)或complete→ 立即就绪;其它状态 → 等到backfill_wait(默认 10s)后报 busy;读错按就绪(写阶段再暴露真错)。StoreOutcome::Skipped,既不收集其 rollout 目标、也不写其 DB。AllRows)且任一库 backfill 进行中,整轮全部 Skipped;--sqlite-only(RolloutScope::None,不碰 rollout)仍写其就绪库。Partial(2)、全跳过 =Failed(1);--sqlite-only的 App 持久性告警改为仅当 App 库真被更新才打。更新 Codex 后那段 backfill 运行期间,完整
sync会整轮跳过并提示稍后重跑(退出码 1),只有--sqlite-only会写非重建中的库。这是有意的数据安全取舍——不与 Codex 的重建抢同一批 rollout 文件。backfill 完成后sync恢复正常。并行 Review(Codex × Claude subagent)
reconcile_all_stores_skips_whole_round_when_backfill_running(断言 backfill 运行时共享 rollout 与两库 DB 均不变)。complete→Updated与 sqlite-only-busy→Partial 测试。测试 / 质量
cargo test:53 passed(新增/重写 3 个 backfill 守卫测试)。cargo clippy --all-targets:0;cargo fmt --check:clean。后续
watch多库化(MismatchedRows 跨库语义)→ PR4;--storeflag → 之后。