Repository navigation
Explore timing over the fake driver; a paused query holds back what a call in flight brings back - #485
Merged
Conversation
…plore timing over the fake driver
A pause that landed while a native call was in flight still let that call's
events out when it returned: the meta after execute or after the next result
set, and an error from a fetch or nextResultSet (with its done and free). So
pause/before-execute gave meta before or after the resume, depending on
timing. The reader now parks what follows such a call (begun(),
moveToNextResult, endOrPark), as it already did for fetched rows, so a paused
query emits nothing until it is resumed. An error at execute while paused is
not held yet: beginQuery queues the free before it rejects.
test/contract/explore.js replays each recorded scenario many times over the
fake driver with jittered timing, so the scenario's timers and the JS layer's
steps land at different points against the driver's results; every run must
match the corpus with no violations. It found the meta above. The native
logs now carry timestamps, and the fake holds each result for as long as the
driver took, so timer-driven scenarios replay with the server's timing.
New scenarios: pause/during-execute-then-{result,error} and pause/during-fetch
(a pause landing while the query executes, or while a fetch is in flight).
pause/before-execute, pause/during-execute-then-result and pause/during-fetch
are agreed. All 83 native logs re-recorded with timing.
Full suite: 992 passing. Replay: 84 passing. Explorer: 83 of 83 held over 6
timings each.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ding on every platform pause/during-fetch is paused by a timer, so how its rows split around the pause depends on timing; on the CI runners it came out 950/50 against 800/200 recorded. Only the explorer compared timed scenarios by shape and total rows; the real-server contract test, the replay and capture.js compared the exact split. corpus.matchesScenario now does this for all of them. Every native recording is now replayed on every platform, compared with the corpus of the platform it was recorded on: the replay tests the JS layer, which is the same everywhere, and only the driver differs. The Windows recordings therefore also run on Linux CI, and on macOS, which has no server and had no behavioural test; the macOS job now runs the replay. The replay suite also runs the pause, cancel and queue recordings at two fixed seeds of jittered timing, so a timing regression fails CI and replays with --seed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
The fix (v6 behaviour)
A pause that landed while a native call was in flight still let that call's events out when it returned. That meant the
metaafter execute or after the next result set, and an error from a fetch ornextResultSet, together with itsdoneandfree. Sopause/before-executegavemetabefore or after the resume, depending on timing.The reader now parks what follows such a call (
begun(),moveToNextResult,endOrPark), as it already did for fetched rows. A paused query emits nothing until it is resumed. This settles the open question inHANDOVER.md.Not held yet: an error at execute while paused.
beginQueryqueues the free before it rejects, so holding the error would letfreeout first.The explorer
test/contract/explore.jsreplays each recorded scenario many times over the fake driver. Each result is held for its recorded latency, give or take a fifth, plus a few ms. The scenario's own timers and the JS layer's steps then land at different points against the driver's results. Every run must match the corpus, with no violations. This is how themetaabove was found.timedscenario, one paused by a timer, is compared by shape and total rows, because how the rows split around the pause is down to timing.--seed n --runs 1replays exactly that timing.New scenarios
These are real-server scenarios: a pause landing while the query executes (
pause/during-execute-then-result,-then-error), and while a fetch is in flight (pause/during-fetch). SQL Server sends nothing of a batch until awaitforin it is over, unless what comes before it fills a packet. That is why the first two pause during execute.pause/before-execute,during-execute-then-resultandduring-fetchare agreed.during-execute-then-errorstays unreviewed, because it still has nodone, which is the error-path gap for #479.Testing (Windows, localdb)
waitfors.🤖 Generated with Claude Code