Repository navigation
test(driver-turso): the cross-process autonumber pin starts its writers once and stops waiting on fsync - #23218
Merged
objectstack-fleet[bot] merged 4 commits intoOct 13, 2026
Conversation
…sync The cross-process autonumber pin spent its wall on two things it does not assert: a tsx start-up per writer per round, and an fsync per commit on a throwaway temp database. The writers now start once and serve every round over stdin/stdout, and each sets synchronous = OFF on its own connection; the lock protocol and every pin are unchanged. Claude-Session: https://claude.ai/code/session_01P88ehrZ6hM19hBzdpsQTTo Co-authored-by: Claude <noreply@anthropic.com>
…stered A writer's start-up was about 40 ms of compiling the package's source and about 2 s of loading its dependencies' built code through tsx's require hook, which plain Node loads in about 1.2 s. The writer now requires those dependencies first, then registers tsx through its public CJS API and requires the source, whose requires hit the cache. The phase times join the measurement line. Claude-Session: https://claude.ai/code/session_01P88ehrZ6hM19hBzdpsQTTo Co-authored-by: Claude <noreply@anthropic.com>
The read-then-write mutation, re-run on the new shape, goes red in 6 of 8 runs with no gap and 5 of 5 with a 1 ms gap; the earlier shape went red in 1 of 5 with no gap on the same box. A command written to a writer that already died now fails with that writer's stderr. Claude-Session: https://claude.ai/code/session_01P88ehrZ6hM19hBzdpsQTTo Co-authored-by: Claude <noreply@anthropic.com>
…rso-autonumber-test-budget Claude-Session: https://claude.ai/code/session_01P88ehrZ6hM19hBzdpsQTTo Co-authored-by: Claude <noreply@anthropic.com>
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
objectstack-fleet
Bot
deleted the
claude/issue-23182-turso-autonumber-test-budget
branch
October 13, 2026 10:13
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.
Part of #23182 (row 2)
Clause-②: no
Row 2 of #23182 only:
@objectstack/driver-turso,src/turso-remote-autonumber-concurrency.test.ts, read at 29.3 s in run38228297391. Refresh PR #23141 lists it over 10 s in 6 of the 7 hourly full-battery runs that executed it. #23182 remains open for rows 1 and 3 to 6.What changed (one file, test-only)
The file pins cross-process autonumber atomicity on the remote face: two writer processes and one libSQL database file must give N distinct numbers, monotonic per writer, with evidence that the writers overlapped. Most of its time went to work it does not assert on. Measured at
d4aaeaf0eon this 4-vCPU container, one round took about 4.4 s:node --import tsx, then the driver's dependencies (@objectstack/driver-sqland what it imports,@objectstack/spec,@libsql/client) loaded through tsx's hook: ~2 s, against ~1.2 s under plain Node. The package's own source compiled in ~40 ms.createis 3 statements (reserve, insert, read back). A single writer took 5.9 ms per create withsynchronous = FULLand 1.2 ms withsynchronous = OFF.A round whose writers did not overlap also re-spawned both writers.
Three changes, none to what is asserted:
require('tsx/cjs/api').register()and requiressrc/index.ts. The source is still compiled by tsx, and the dependencies are the same modules, already in the require cache.tsxis already a declared devDependency, andtsx/cjs/apiis one of its public exports.PRAGMA synchronous = OFFon its own connection. That drops only the disk flush at commit, on a throwaway temp file. The journal mode, the locks and the busy timeout are unchanged, so the cross-process serialisation the pin depends on is unchanged.The round's ready and write times now join the existing measurement line, so a slow CI run can be attributed from its log.
Kept as they were: N = 200 per writer, at most 3 rounds, every pin, and the NOT MEASURED skip. N was not reduced: writes are no longer the cost, and a smaller N would only lower how often a broken counter is caught (see the reverse verification below).
Readings
The CI per-file number is vitest's module line (
✓ path (1 test) Nms). All readings below are from this container underscripts/pm/os-verify-lock.sh, on a shared box (other seats' unlocked work was running), with vitest's default reporter (agent-detection variables unset, as in CI).d4aaeaf0e83ece05da)driver-tursopackage (88 files)83ece05da)driver-sql's suite at once794b74409, same run as BASE's 8973)Writer changes per round: 2 to 40 before, 141 to 221 after (unmutated runs).
CI reading for the after-state: NOT MEASURED here. Job logs and artefacts redirect to an Azure blob host that this container's egress proxy refuses (403). This PR's own Test Core shard carries the file's module line and the measurement line in its log.
Reverse verification (ablation)
Mutation: the warm reservation (
UPDATE … SET last_value = last_value + 1 … RETURNING) split into aSELECT last_valueand then anUPDATE … SET last_value = ?(read-then-write), once with no gap and once with a 1 ms gap.scripts/ablation-replace.mjs: the anchor hit went 1 → 0 and the blob changed. The restore was proven after every leg: blob equal to HEAD andgit diff HEADempty.nextRemoteSequenceValue.toString()carries the marker. Nodistis involved, since both the parent and the writers runsrc.UNIQUE constraint failedin a writer's error list, as the file's header recorded. Observed: that direction in every red run.794b74409and83ece05da)7e0c6cc50(before the dependency preload)A non-atomic counter is caught more often than before, not less: without the fsync the writers interleave far more finely. A zero-gap read-then-write remains a probabilistic catch, as it was at BASE.
Gates and tests (at
83ece05daunless named)pnpm --filter '@objectstack/driver-turso...' buildgreen, after mergingorigin/main.pnpm --filter @objectstack/driver-turso typecheck(tsc --noEmit) is green, and its tsconfig includessrc/**/*, tests included. The package suite ran 88/88 files: 2373 passed, 33 skipped, the same counts as BASE.pnpm check:driver-conformancebefore the first edit and after the last commit read50 covered cell(s), 0 in the DEBT ledger, 0 exemptboth times.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackgave 51 commands, identical to the dispatch-time set, and all ran. The--ranverdict reads51 derived, 51 run, 0 NOT-MEASURED, 0 UNRUN. Three first answered exit 3 (unmet prerequisites) and were re-run green after their remedy:check-plugin-teardown-shape --self-testneededgit fetch --unshallow, andcheck:lean-entry-closureandcheck:dual-build-cjs-loadsneeded packagedists, restored from the turbo cache.--no-inline-configon the one changed file linted 1 file with 0 errors and 0 warnings. The file is in eslint's population (--print-configreturns a config for it). The config enables no type-aware linting (the resolvedparserOptionsareecmaVersionandsourceType), so this diff cannot move any other file's verdict.check:nul-bytesis green, and a control-byte self-scan of the file found 0 lines.Changeset
None. The diff is test-only: the changed file is not in
driver-turso'sfiles[](dist,README.md,CHANGELOG.md). Measured on adistbuilt after the merge, four symbols unique to the test (PRELOADED_DEPENDENCIES,WORKER_SOURCE,REPLY_DEADLINE_MS,turso-autonumber-concurrency-) have 0 hits, and the positive controlnextRemoteSequenceValuehas 6. Label:skip-changeset.Acceptance notes
@objectstack/coreimport cost. It alone takes about 0.9 s to import under plain Node and dominates a writer's remaining start-up of about 1.2 s. That is an observation about another package's import cost, not a defect; it is not filed.Generated by Claude Code