Repository navigation
exec() refuses SQL without a statement; new events in the runtime's async context - #7
Merged
Merged
Conversation
mkotelnikov
force-pushed
the
ccr-ab3c0d30-6du8do-small-gaps
branch
2 times, most recently
from
October 27, 2026 07:02
eba8fd6 to
8a6db97
Compare
…ime's async context sql.ingest(sql) (workerd, experimental): runs the complete statements at the start of an SQL chunk (quotes, comments and trigger bodies respected) and returns the rest as `remainder`, with rowsRead, rowsWritten and statementCount; an SQL dump can be fed through it in chunks of any size. sql.exec(), as workerd: SQL with no statement (`""`, `";"`) or a last statement of comments alone throws "SQL code did not contain a statement."; a syntax error is worded `near "X": syntax error at offset N: SQLITE_ERROR` (the drivers prepare statements without their `;`, where SQLite says "incomplete input": reworded as the syntax error at that `;`). No celld recording depends on the old wording. wd-sql-default now gets past ingest and stops at workerd's wording of other SQLite errors (SQLITE_MISMATCH, SQLITE_AUTH), where cellb follows celld: still a known gap, judged by workerd. A call to a Durable Object is a new event, as on Cloudflare: events and constructors start in the async context the runtime was made in, not the caller's (AsyncLocalStorage.snapshot + a fresh AsyncResource per event on Node, so a store one event sets does not reach the next; the polyfill's frame in a browser). A host can still scope a whole runtime (p09 does). Tests: p15 (workerd's ingest assertions, a dump in chunks of 1–81 bytes with strings, comments and a trigger), p16 (a direct and an object-to- object call do not see the caller's store; the runtime's store reaches events and constructors), the async-context worker's expectation now Cloudflare's (Node and Chromium). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8
mkotelnikov
force-pushed
the
ccr-ab3c0d30-6du8do-small-gaps
branch
from
October 27, 2026 07:07
8a6db97 to
5c9dca9
Compare
mkotelnikov
pushed a commit
that referenced
this pull request
Oct 27, 2026
"Queues: a delayed message sent on cellb is delivered by celld" failed now and then in CI (#5, #7). celld wakes cells from its wake index by minute (wake/entries/<UTC minute>/…): a message due in a later minute than celld started in is woken at its next scan, up to a minute on, and the test polled for 20 s. Reproduced every time by sending at :54 of a minute (delivered 59 s after celld started); cellb writes the same entry celld writes for its own delayed messages. The test now polls for up to 80 s (timeout 150 s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8
main (48f6222) brought its own sql.ingest(), worded as celld words it and checked against celld (conformance project sql-ingest). This PR's ingest, its workerd wording ("… at offset N: SQLITE_ERROR") and its takeCompleteStatements give way to it: main's sql-split.ts, sql-storage.ts, scenarios.ts and gaps.md, then on top: - exec() refuses SQL with no statement, or a last one of comments alone ("SQL code did not contain a statement."), as workerd and celld do (lacksStatement, on main's completeSqlStatements). With it, wd-sql-default stops at the same assertion as celld; its known gap now names only celld's stack frames in the report. - gaps.md keeps this PR's entry for events starting in the runtime's async context. - p15 expects celld's ingest wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8
"Queues: a delayed message sent on cellb is delivered by celld" failed now and then in CI (#5, #7). celld wakes cells from its wake index by minute (wake/entries/<UTC minute>/…): a message due in a later minute than celld started in is woken at its next scan, up to a minute on, and the test polled for 20 s. Reproduced every time by sending at :54 of a minute (delivered 59 s after celld started); cellb writes the same entry celld writes for its own delayed messages. The test now polls for up to 80 s (timeout 150 s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8
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.
Updated after
main(48f6222) brought its ownsql.ingest(). This PR'singest, and its workerd-style error wording, gave way tomain's, which follows celld and is checked against celld's recording (sql-ingest). What remains:1.
sql.exec()refuses SQL without a statement"",";"), or whose last "statement" is only comments (SELECT 1; -- note), now throwsSQL code did not contain a statement., as workerd and celld do. cellb used to run it, or failed with "statement has been finalized".lacksStatementinsql-split.ts, built onmain'scompleteSqlStatements.wd-sql-defaultstops at the same assertion as celld (ingest's syntax error). Its known gap now names only the remaining difference: celld's report carries its own stack frames.main'sdocs/gaps.mdlisted forwd-sql-default.2. A call to a Durable Object is a new event
On Cloudflare, a called object doesn't see its caller's
AsyncLocalStoragestores. cellb now matches: every event delivered to an object (ObjectHost.deliver), and the constructor, starts in the async context the runtime was made in (core/async-context.ts).AsyncLocalStorage.snapshot(), reached throughprocess.getBuiltinModule, so core still imports nothing from Node. Each event also gets a freshAsyncResourcecreated inside the snapshot. Before Node's AsyncContextFrame,als.run()writes the store onto the current resource, so without this anals.run()in one event leaked into the next event started inside it.node:async_hookspolyfill's frame.createCellRuntimeran reaches every event, which is how p09 attributes each scenario's logs.3. The failed
interopcheckIt was "Queues: a delayed message sent on cellb is delivered by celld", a timing flake, also fixed in #9.
Tests
test/p15-sql-ingest.test.ts:exec()refusals for"",";"and a trailing comment;main'singestremainders, and its celld wording of syntax errors;test/p16-async-context.test.ts: neither a direct call nor an object-to-object call sees the caller's store; a store active when the runtime was made reaches events and constructors.test/async-context-worker.ts: the callee sees no store, on Node and in Chromium.main:pnpm run interop(celld conformance and interop): 123 passed, 6 expected failures;interop:browser: 4 passed;🤖 Generated with Claude Code
https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8