Skip to content

TC-737: Seek quiet KV sync prefixes on PostgreSQL - #300

Open
samgbafa wants to merge 5 commits into
mainfrom
skgbafa/tc-737-quiet-prefix
Open

samgbafa wants to merge 5 commits into
mainfrom
skgbafa/tc-737-quiet-prefix

Conversation

@samgbafa

@samgbafa samgbafa commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Change

  • PostgreSQL current_kv(space, key COLLATE "C") index, built and dropped concurrently outside a transaction. The custom migration runner commits before concurrent DDL, retries after removing an INVALID index, retains ordinary DDL/history atomicity, and rejects PostgreSQL fresh/refresh/reset before mutation. Review the runner changes in tinycloud-core/src/migrations/mod.rs and db.rs separately from the query/index changes.
  • For non-root PostgreSQL kv/sync, a materialized 64-row sequence-index window checks raw candidates before prefix/floor filtering. A full window without a qualifying row falls back to separate C-key exact/descendant probes. A positive poll reads a materialized, sequence-ordered limit+1 raw-row window; if that cannot prove a complete page, it uses the original scoped feed. This bounds dense-prefix continuations under generic plans as well as quiet-prefix empty polls. Cursor bytes, floor/tombstone rules, whole-event groups, root feeds, and SQLite/MySQL query paths remain unchanged.
  • PostgreSQL kv/list uses C byte collation for both after and ordering, matching SQLite BINARY. Bare key and descendants are queried separately. A signed pre-cutover v1 list cursor returns HTTP 400 with "restart listing"; newly issued cursors use v2.

PG18.6 evidence

Durable logs and explanation: /home/tinycloud/scratch/tc-737/pg18-proof/ (linked from Linear TC-737). Local isolated postgres:18.6, en_US.utf8, 64 MB shared buffers, 25 connections. Production is PlanetScale PostgreSQL 18.6 in us-east-1 (Amos); PG16 is extra evidence only.

  • delta-dense-window-actual-builders.log: actual prepared builders, plan_cache_mode=auto and genuine force_generic_plan ($n visible). A has one busy/only and 300,000 noise/ keys; B has 300,000 busy/ keys, with real middle/group/late/end event anchors. The 64-row preflight uses idx_current_kv_space_order: dense middle at most 10 buffers plus a 501-row bounded feed at most 42; late at most 10 plus a 100-row feed at most 14; caught-up zero candidates in 4 buffers. Quiet A at most 9 preflight buffers then C-index probes at most 5 buffers each, filtering at most one prefix row. A moved matching key beyond the full window remains deliverable. Runtime checks cover bare/slash, group completion and continuation, empty state/byte-identical cursor, and out-of-prefix isolation. These shared-slot plans are not controlled latency measurements.
  • delta-skew-actual-builders.log: preceding C-key probe and listing-plan proof; A's rare listing and quiet probes use index bounds under both modes, and B's 501-row listing takes 28 buffers. Astra's earlier c70cb97 review found that the unconditional C probe scanned up to 300,000 consumed B keys; the new bounded window addresses that P2. The first PG18 baseline measured 58.762 ms/600,000 rows filtered versus 0.078 ms/one filtered after the C index, but alone did not cover cross-space or dense skew.
  • index-build-and-explain.log: CREATE INDEX CONCURRENTLY took 1.061 s, observed ShareUpdateExclusiveLock, and 10 reads and 10 writes completed during the build (max 1.170 ms and 1.094 ms). The exclusive 15:30:02–15:33:12Z window was released; the later shared-slot PG18 container was also removed and the claim released.
  • joint-upgrade.log: PG18 fresh and upgraded 1.20.6 schemas; db: page account session discovery #296 _000000 alone, then db: page account session discovery #296 → TC-737 _010000 → TC-735 _020000 at TC-735 head 5f34b4d372108e2619e467cea71c41c117c3db0a. History and schema objects verified in an isolated checkout; no TC-735 worktree edits.
  • Final-head focused checks: core kv_sync 26 passed/1 ignored, core kv_list 7 passed, node kv_sync 14 passed, signed HTTP list-cursor test 1 passed, 2 × 300k actual-builder fixture 1 passed, cargo clippy --workspace --all-targets -- -D warnings passed. Earlier runner regressions covered a real failed concurrent index, INVALID-index recovery, transactional rollback, and PG maintenance rejection; the earlier serialized workspace suite was 1079 passed, 9 ignored, 4 CI-only filtered. The only lint output is the existing dependency future-incompatibility warning for proc-macro-error2.

Backend, review and release gates

  • MySQL receives no index in this change (no production use), and the index migration is a clean no-op on MySQL/SQLite. No MySQL performance claim. Already-running older writers remain SQL-compatible; restarting an old binary after the TC-737 migration history row fails on unknown migration and requires roll-forward.
  • db: page account session discovery #296/TC-1195 _000000 precedes TC-737 _010000; TC-735 proposes _020000. Whichever TC-737/TC-735 PR merges second must rebase, rename its migration later if necessary so it sorts/registers after every migration already on main, and rerun upgraded-schema order proof. Amos release order: revert fix(TC-1132): harden webhook, quota, and tunnel egress #292 → 1.20.8 (db: page account session discovery #296) → 1.20.9 (attestation: hash report data before GetQuote #295) → 1.20.10 (TC-1071) → TC-737 → TC-735; each its own release on Sam's word. No merge or deployment from this PR.
  • Astra's scoped migration-runner PASS at 798440d and Sol's scoped security APPROVE at c70cb97 retain separate attribution. Astra's exact-head query/index PASS at c02d6d30df2e24b231cccd80dded4f227c65d669 resolves the dense-prefix P2. CI and Amos gates remain open.

Linear: TC-737

@samgbafa

Copy link
Copy Markdown
Contributor Author

PASS — scoped custom migration-runner review at 798440d. No remaining findings in this scope.

Reviewed tinycloud-core/src/migrations/mod.rs and tinycloud-core/src/db.rs, the invalid-concurrent-index retry and ordinary-DDL rollback regressions, and the final maintenance-method guard/documentation delta. This is not the independent quiet-prefix query/planner/index-design review.

The runner preserves ordinary PostgreSQL DDL/history atomicity per batch and scoped timeout exemption, committing before concurrent index DDL and recording its history only after success. The retry regression requires a real failed CREATE UNIQUE INDEX CONCURRENTLY, indisvalid=false, and recovery to a valid (space, key COLLATE "C") index. TC-1195 precedes TC-737 in registration and the release-tail ordering guard; SQLite/MySQL retain standard runner behavior.

The earlier P2 is resolved: mod.rs:152–162 and 199–230 reject PostgreSQL fresh/refresh/reset before any schema/history work, including transaction inputs. The regression at 410–458 checks all three refusals, unchanged history count, retained stray table, and a valid index. docs/releasing.md:225–235 documents this restriction and the old-binary restart/roll-forward constraint. Already-running old writers remain SQL-compatible; restarting an old binary after the new history row is not a safe rollback.

Evidence: read-only source and SeaORM dependency review. PG18 test and clippy outcomes are owner-reported; I did not rerun suites, benchmarks, or database mutations. The second-merge TC-735/TC-737 rebase/order/reproof gate remains required. This verdict does not authorize merge or deploy.

@samgbafa

Copy link
Copy Markdown
Contributor Author

APPROVE: see TC-737

@samgbafa

Copy link
Copy Markdown
Contributor Author

REQUEST_CHANGES: see TC-737

@samgbafa

Copy link
Copy Markdown
Contributor Author

APPROVE: scoped Sol security delta at c70cb97; see TC-737

@samgbafa

Copy link
Copy Markdown
Contributor Author

REQUEST_CHANGES: c70cb97 (query/index delta); see TC-737

@samgbafa

Copy link
Copy Markdown
Contributor Author

PASS: c02d6d3 (query/index delta); see TC-737

@samgbafa

Copy link
Copy Markdown
Contributor Author

PASS: c02d6d3 (full 798440d-to-c02d6d3 product delta); see TC-737

This branch has not been deployed

No deployments
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