fix(sqlite): shim db.transaction(fn) on node:sqlite DatabaseSync#123
Merged
Merged
Conversation
Follow-up to tickernelz#121. `bun:sqlite` and `better-sqlite3` both expose `db.transaction(fn)` which returns a callable that wraps `fn` in BEGIN/COMMIT (auto-ROLLBACK on throw). `node:sqlite`'s `DatabaseSync` has no equivalent. `handleAddMemory` in `api-handlers.ts` and `client.addMemory` in `services/client.ts` both use this method to atomically insert a memory row, so the POST /api/memories endpoint and any auto-capture path crash under Node with `db.transaction is not a function`. The original PR caught the `db.run(sql)` gap but missed the transaction gap because the local E2E smoke test exercised CRUD without atomicity. Single-mode semantics only (BEGIN); the `.deferred` / `.immediate` / `.exclusive` variants from better-sqlite3 are not exercised by this codebase. Best-effort rollback (ignores secondary errors from the ROLLBACK statement after partial state). ## Verification - `bun test`: 143 pass / 0 fail (Bun path unchanged) - `bun run typecheck`: clean - `bun run build`: clean - `npx prettier --check`: clean - Node 26 E2E with commit + rollback: - tx() inserts a, b → SELECT returns [{t:"a"},{t:"b"}] - txFail() throws after inserting c → SELECT still returns [{t:"a"},{t:"b"}] - Reproduced and patched the original failure path locally (POST /api/memories now returns success after applying this shim).
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.
Follow-up to #121.
Summary
bun:sqliteandbetter-sqlite3both exposedb.transaction(fn)which returns a callable that wrapsfninBEGIN/COMMIT(auto-ROLLBACKon throw).node:sqlite'sDatabaseSynchas no equivalent.handleAddMemory(services/api-handlers.ts) andclient.addMemory(services/client.ts) both use this method to atomically insert a memory row, so under Node:POST /api/memoriescrashes withdb.transaction is not a functionReproduced today on opencode 1.15.10 (anomalyco fork) + Node sidecar:
$ curl -X POST http://127.0.0.1:4747/api/memories \ -H 'Content-Type: application/json' \ -d '{"content": "test", "containerTag": "scope-project-xxx", "type": "fact"}' {"success":false,"error":"TypeError: db.transaction is not a function"}(After patching the sharp install separately — opencode-mem still ships
@xenova/transformerswhich needs sharp's native binary, but that's a pre-existing packaging issue, not in scope here.)Fix
Subclass
DatabaseSyncto add atransaction(fn)method matching the bun:sqlite / better-sqlite3 signature. Single-mode (BEGIN) semantics only — the.deferred/.immediate/.exclusivevariants are not exercised by this codebase, can be added in a follow-up if needed.Why it slipped through #121
My local E2E smoke test exercised CRUD via prepared statements but never called
db.transaction(). The Bun test suite covers a lot of surface but doesn't reach the bun:sqlite-specific transaction path in a Node-runtime-only context. Today's session log on the live Node sidecar surfaced the gap immediately on the firstPOST /api/memories.Verification
bun test: 143 pass / 0 fail (Bun path unchanged)bun run typecheck: cleanbun run build: cleannpx prettier --check: cleanSELECT * FROM mreturns both rowsSELECTstill shows the pre-tx state (rollback worked)POST /api/memoriesnow returns{success:true}as expected.Environment