Skip to content

A declared table reads what is on disk when each query runs - #1577

Merged
thekevinbot merged 5 commits into
mainfrom
bot/1572-fresh-red-1104
Nov 4, 2026
Merged

thekevinbot merged 5 commits into
mainfrom
bot/1572-fresh-red-1104

Conversation

@thekevinbot

@thekevinbot thekevinbot commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #1572

Restart of #1573, red first. Commit 1 (d4187d13) holds only tests. The fix is 54a009cb, then a merge of main to resolve the bind-params conflict (#1576/#1578).

What changes

A query on a long-lived DirSQL reads what is on disk when it starts, in Rust, Python and TypeScript. Before reading, it walks each named table's glob, stats every match, re-reads each file whose stat moved or that changed within the last two seconds, and drops the rows of files that are gone. The row events those re-reads produce reach watch() streams and the next poll, once each.

  • TypeScript: query() / queryOrdered() run the re-reads on the JS thread (where onFile can run) through a new read_changes(), then send the SQL to the threadpool.
  • Before watch starts: a change a query reads before any watcher exists still reaches the first watch() stream or poll.
  • One-shot dirsql query: unchanged; it still reads the index as built.

Red run (commit 1, tests only)

Local e2e on the unfixed build

  • Python (tests/e2e/fresh_declared_repros_test.py): 5 failed, 1 passed.
    • Failed: no-watch it_reads_a_file_written_after_ready and it_reads_a_create_an_edit_and_a_delete; it_is_read_by_the_next_query_and_streamed_once; it_reads_every_write_before_it; it_reads_a_create_with_a_watch_consumed.
    • Passed: the path-table test. A path table is already fresh on main, so it guards against regressions and can't be shown red.
  • TS (tests/e2e/fresh-declared-repros.test.ts): the same 5 failed and the path-table test passed.

Tests per tier

Tier New tests
Rust integration 33: hammer 8, edges 13, oracle 2, events 2, Windows open handle 4, concurrent 3 (watch consumer, poll_events, between ready and watch), plus 1 FK in foreign_keys.rs
Rust CLI 2: server and REPL hammers
Rust unit 1 changed (a_query_before_any_watcher_hands_its_row_events_to_the_first_poll), 1 added (read_changes_reads_the_disk_with_fresh_reads_off)
Python binding 16
Python e2e 6 (5 red on main)
TS binding 16
TS e2e 6 (5 red on main)

Known limits

  • Memory: a query that reads a change queues its row events for watch consumers even before any watcher starts. A process that queries a changing tree and never watches keeps those events in memory without bound.
  • TS event loop: the stat walk and the onFile re-reads run on the JS thread, so they block the event loop for that time.
  • Stat-based limits: a write through a shared mmap, NFS attribute caching, and a clock stepped backwards can each hide a change (documented in docs/reference/sdk.md).
  • Windows open-handle writes: not a gap. NTFS ChangeTime moves before write returns, and the 4 open-handle tests were red before the fix.

Green run (897b2b5)

All 75 checks pass, including mutation on every language and the CI Gate.

E2E Verification

Run on the fixed build after merging main (501e509).

  • Python: testing-conventions e2e attest on the e2e files a declared table can reach: declared_table_name, fresh_declared_repros, on_file_query, use_case_{dossier,join,notebook,transcripts}, frontmatter/jsonl parse speed, fanout, plugin_discovery, plugin_extension_discovery, extension_package, server_speed, query_contract, repl_interactive, watch_speed, sigint_interrupt.
    • Result: 46 passed.
    • Earlier full-suite run (just test-e2e, -x): 32 passed, then it stopped on the path-table glob speed case ./docs/ (median 1.18x vs rg, host load 11.3).
    • That case was left out of the impacted set because a path-table query with no named tables never runs the refresh.
  • TS: just e2e-attest-ts (pnpm test:e2e), 25 passed (8 files), including the 6 fresh-declared repros.
  • Rust: cargo test -p dirsql --features cli, 2255 passed, 0 failed.

# Conflicts:
#	docs/reference/sdk.md
#	packages/rust/src/lib.rs
#	packages/ts/napi/src/lib.rs
#	packages/ts/src/dirsql.ts
@thekevinbot
thekevinbot merged commit 1e69f10 into main Nov 4, 2026
99 checks passed
@thekevinbot
thekevinbot deleted the bot/1572-fresh-red-1104 branch November 4, 2026 19:32
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.

Declared tables must be fresh on every query, with or without watch()

1 participant