feat(sdk): Phase 11.8 multi-handle SDK shape (SQLR-22)#129
Merged
Conversation
Closes the end-to-end gap from 11.7. The retry-error machinery (BusyError / errorKind / ErrBusy) was reachable through every SDK after 11.7 — but each `sqlrite.connect()` / `new Database()` / `sql.Open()` built an *isolated* backing DB, so the retry idioms were untriggerable. This slice exposes the engine's `Connection::connect()` through the public SDK surfaces so apps can finally mint sibling handles that share state. Picked ahead of plan-doc 11.5 (durability) for the same reason 11.5–11.7 jumped the queue: visible user value first. After this PR, the canonical `BEGIN CONCURRENT` retry loop pattern works end-to-end through Python and Node. C FFI ([`sqlrite-ffi/src/lib.rs`]): - new `sqlrite_connect_sibling(existing, out)` function. Thin wrapper around the engine's `Connection::connect`. Sibling has its own pointer + lifecycle but shares Database state. - header regenerated via build.rs. - 2 new tests: connect_sibling_mints_a_handle_that_shares_state (real cross-handle BEGIN CONCURRENT conflict through the public API) and connect_sibling_rejects_null_inputs. Python SDK ([`sdk/python/src/lib.rs`]): - new `Connection.connect()` instance method. Acquires the inner Mutex<RustConnection>, calls `inner.connect()`, wraps result in a fresh pyclass with its own Mutex. Inherits the parent's ask_config. - 4 new tests: sibling sharing, outliving closed parent, raise on closed connect, and the headline busy-round-trip-via-siblings. Node.js SDK ([`sdk/nodejs/src/lib.rs`]): - new `Database.connect()` method on the napi-rs class. Same shape — sibling Database with its own RefCell + ask_config clone. - 4 new tests including the cross-sibling BusyError round trip using 11.7's errorKind classifier. Go SDK: deliberately skipped. database/sql's pool model already gives sibling-like behavior across `db.Conn(ctx)` calls within a single `sql.Open`, but exposing a *cross-pool* sibling shape through `database/sql` would need a process-level path → Database registry. Deferred to a follow-up (roadmap 11.11). WASM SDK: deliberately skipped (single-threaded browser + wasm-bindgen lifetime complications). Same deferral as 11.7. Workspace: 654/654 Rust tests pass (was 652 + 2 new FFI). Python + Node SDK CI jobs will exercise the new sibling-handle tests on the next CI run. fmt + clippy + doc clean on changed files. Roadmap renumbered again: - plan-doc 11.5 (checkpoint) → roadmap 11.9 (was 11.8) - plan-doc 11.7 (indexes) → roadmap 11.10 (was 11.9) - REPL .spawn + bench workload + Go multi-handle = roadmap 11.11 - plan-doc 11.9 (docs) → roadmap 11.12 (was 11.11) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Summary
Closes the end-to-end gap from 11.7. The retry-error machinery (
BusyError/errorKind/ErrBusy) was reachable through every SDK after 11.7 — but eachsqlrite.connect()/new Database()/sql.Open()built an isolated backing DB, so the retry idioms were untriggerable. This slice exposes the engine'sConnection::connect()through the public SDK surfaces so apps can finally mint sibling handles that share state.Picked ahead of plan-doc 11.5 (durability) for the same reason 11.5–11.7 jumped the queue: visible user value first. After this PR, the canonical
BEGIN CONCURRENTretry-loop pattern works end-to-end through Python and Node.What ships
C FFI (
sqlrite-ffi/src/lib.rs)sqlrite_connect_sibling(existing, out)function. Thin wrapper around the engine'sConnection::connect. Sibling has its own pointer + lifecycle but shares Database state.build.rs.Python SDK (
sdk/python/src/lib.rs)Connection.connect()instance method acquires the innerMutex<RustConnection>, callsinner.connect(), and wraps the result in a fresh pyclass. Inherits the parent'sask_config.Node.js SDK (
sdk/nodejs/src/lib.rs)Same shape — sibling
Databasewith its ownRefCell+ask_configclone.Go SDK — deliberately skipped
Go's
database/sqlpool model already gives sibling-like behavior acrossdb.Conn(ctx)calls within a singlesql.Open, but exposing a cross-pool sibling shape throughdatabase/sqlwould need a process-level path → Database registry. Genuinely non-obvious; deferred to roadmap 11.11.WASM SDK — deliberately skipped
Single-threaded browser +
wasm-bindgenlifetime complications. Same deferral as 11.7.Test plan
cargo build --workspace --exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks --all-targets— cleancargo test --workspace --exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks— 654/654 (2 new FFI tests)cargo clippy— no new warnings on changed filescargo fmt --all -- --check— cleancargo doc— no new warnings on changed filesNew tests
connect_sibling_mints_a_handle_that_shares_stateexercises a real cross-handleBEGIN CONCURRENTconflict through the publicsqlrite_connect_siblingfunction.connect_sibling_rejects_null_inputscovers the null-pointer guard rail.BEGIN CONCURRENTbusy round-trip via siblings.errorKindfrom 11.7 to confirm the busy classification works end-to-end.Subtle / informational
sqlrite.connect(path)(module-level free function, opens a fresh DB) andConnection.connect()(instance method, mints a sibling) now both exist. Mirrors the Rust API (Connection::open+Connection::connect) so it stays consistent across languages, but worth a callout in the README when the docs sweep lands (11.12).errorKind/ErrorKindto the top-level ESM import;require()inside a.mjstest body is invalid.Roadmap renumbering (third time, getting practiced at this)
.spawn+ bench workload + Go multi-handle → roadmap 11.11Called out in the roadmap entries so plan-doc references remain readable.
🤖 Generated with Claude Code