query: build models once per release, read snapshots in place - #7
Merged
Merged
Conversation
A build forked one worker per query, and every worker loaded every snapshot and rebuilt every model before running its one SELECT. A project with a few models and a dozen queries paid for the same joins a dozen times, and each repetition counted against that query's 60 s deadline. build now sends all its queries to a single worker as a batch. The worker loads the snapshots, shuts external access and builds the models once, then runs each query in turn and reports one line per query. The sandbox is unchanged: every query is still admitted only as a single SELECT, held to its own row limit, and runs on the closed side of the external-access door. The deadline is per step rather than per batch: loading and models get 60 s, and each query gets its own 60 s after that. A timeout or failure now names the model or query it belongs to; "query deadline exceeded" used to say neither. runQuery is a batch of one, so query, test and describe behave as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The worker copied every column of every snapshot into its in-memory database before running anything. Past the 1 GB memory cap that copy spills to disk, and every model then runs at disk speed. Snapshots are now views read in place, so a model scans only the columns it uses. File access is allowed for exactly the declared snapshot paths, set before external access is shut; DuckDB refuses to widen the list or reopen access afterwards, and a file beside a snapshot stays out of reach. CHAINPLOT_QUERY_MEMORY_LIMIT never reached the worker: its environment is stripped to PATH, HOME and LANG, so the documented override did nothing. The parent now reads and validates it and passes it in the request; a value that is not a size is refused by name. On a project with about 4M event rows behind five models and 19 queries, build went from 345 s to 12 s at the default 1 GB, with identical results. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID:
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. Comment |
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.
A build forked one query worker per query, and each worker copied every snapshot into memory and rebuilt every model before running its one SELECT. On a project with about 4M event rows behind five models and 19 queries,
buildtook 345 s, and on a busy machine single queries ran past the 60 s deadline, so the build failed outright.What changes
query deadline exceededused to name neither.CHAINPLOT_QUERY_MEMORY_LIMITworks. The worker's environment is stripped toPATH/HOME/LANG, so the override documented incapabilities.mdnever reached it. The parent now reads and validates it and passes it in the request; a value that is not a size is refused by name. The default stays 1 GB.runQueryis a batch of one, soquery,testanddescribebehave as before.Why the sandbox holds
allowed_paths, not their directories), set before external access is shut. DuckDB refuses to widen that list or to re-enable access afterwards. A file beside a snapshot,/etc/passwd, and any other path stay unreadable; there are tests for each.docs/security.mdanddocs/capabilities.mddescribe the batch, the exact-path allowlist, the per-step deadlines and the memory override.Testing
pnpm test: 381 passed; the 3 live tests skipped. The first commit alone passes 377.tests/query/batch.test.ts(10): models built once (arandom()model reads the same in two queries), failures and timeouts name the model or query, per-query row limits, external access shut for every query in a batch, a parquet beside a snapshot refused, the memory override reaching the worker and a bad value refused.main, 12 s on this branch at the default 1 GB, 10 s at2GB. All 19 result files are identical tomain's.🤖 Generated with Claude Code