Skip to content

Conversation

@findolor
Copy link
Collaborator

@findolor findolor commented Nov 10, 2025

Motivation

See issues:

Solution

  • The worker template now injects a timeout constant so every worker knows the timeout budget at boot
  • Worker state keeps both a has_leader flag and the configured follower-timeout value, so followers wait only as long as intended before giving up
  • Leader-ping messages, a startup probe, and a Promise::race against the timeout let followers detect leaders quickly and fail fast when the deadline hits

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • included screenshots (if this involves a front-end change)

Summary by CodeRabbit

  • New Features
    • DB construction now awaits worker readiness, with leader detection/probing and structured worker error reporting surfaced to callers.
  • Improvements
    • Queries immediately proceed once the DB handle is available (removed artificial delays); richer parameter support (BigInt, blobs, strict number validation); follower timeout handling for pending queries.
  • Tests
    • Expanded WASM tests for readiness lifecycle, parameter normalization, error propagation, worker messaging, and leader-probing.

@findolor findolor requested review from 0xgleb and hardyjosh November 10, 2025 14:17
@findolor findolor self-assigned this Nov 10, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 10, 2025

Walkthrough

Adds leader-aware worker coordination and structured worker errors; implements a WASM-backed SQLite client with ReadySignal, parameter normalization, worker-template follower timeout injection, updated worker lifecycle messaging, and widespread tests and example updates to await readiness.

Changes

Cohort / File(s) Summary
Worker coordination & leadership
packages/sqlite-web-core/src/coordination.rs
Replace boolean leader flag with LeadershipRole and LeaderPresence; add follower_timeout_ms; add leader probing (start_leader_probe), inter-worker message helpers, follower-timeout handling, and initialization-pending logic for query routing.
Core worker init & error plumbing
packages/sqlite-web-core/src/worker.rs, packages/sqlite-web/src/worker.rs
Create structured worker errors, add make_structured_error, report init errors to host via send_worker_error, start leader probing during init, and install/control-message handling on main-thread worker wrapper.
Channel / message types
packages/sqlite-web-core/src/messages.rs, packages/sqlite-web/src/messages.rs
Add LeaderPing channel message, WorkerErrorPayload struct, and constants WORKER_ERROR_TYPE_GENERIC / WORKER_ERROR_TYPE_INITIALIZATION_PENDING; change MainThreadMessage error field to carry structured payload.
WASM DB API & readiness
packages/sqlite-web/src/db.rs, packages/sqlite-web/src/ready.rs, packages/sqlite-web/src/lib.rs
Add SQLiteWasmDatabase wasm-exported API with async new()/query(), pending_queries/requestId routing, ReadySignal (Pending/Ready/Failed) with Promise lifecycle; move types into modules and re-export.
Errors & conversions
packages/sqlite-web/src/errors.rs
Add SQLiteWasmDatabaseError enum (SerdeError, JsError, InitializationPending, InitializationFailed) and conversions to/from JsValue and WasmEncodedError.
Param normalization & utils
packages/sqlite-web/src/params.rs, packages/sqlite-web/src/utils.rs
New param normalization for JS interop (normalize_params_js) including BigInt→tagged object and ArrayBuffer/Uint8Array→base64 blob; add describe_js_value helper and validate/reject NaN/Infinity.
Worker template & embedded worker
packages/sqlite-web/src/worker_template.rs, scripts/local-bundle.sh
Inject self.__SQLITE_FOLLOWER_TIMEOUT_MS = 5000.0 into generated worker prefix; remove explicit postMessage "worker-ready" emission from embedded template.
Tests, examples & fixtures
packages/sqlite-web/src/tests.rs, packages/sqlite-web-core/src/... (tests), svelte-test/src/routes/*, svelte-test/tests/fixtures/test-helpers.ts
Expand wasm tests (readiness, errors, params, template), update examples/tests to await SQLiteWasmDatabase.new(...), update fixtures and svelte pages, bump local package reference, and minor package.json newline.
Misc (package files)
pkg/package.json, svelte-test/package.json
Trailing newline added to pkg/package.json; bumped local tarball reference in svelte-test/package.json.

Sequence Diagram(s)

sequenceDiagram
    participant App as App (Svelte)
    participant DB as SQLiteWasmDatabase
    participant MainW as Main Thread Worker
    participant CoreW as Worker Scope
    participant Ready as ReadySignal

    App->>DB: new(db_name) (async)
    DB->>MainW: create_worker_from_code(...)
    MainW->>CoreW: spawn worker, init WorkerState (Follower, Unknown)
    CoreW->>CoreW: start_leader_probe() periodically (uses follower_timeout_ms)
    alt leader discovered
        CoreW->>CoreW: set is_leader / has_leader = Known
        CoreW->>Ready: mark_ready()
        CoreW->>MainW: postMessage { type: "worker-ready" }
    else probe timeout / no leader
        CoreW->>MainW: postMessage { type: "worker-error", error: InitializationPending }
        CoreW->>Ready: mark_failed(...)
    end
    Ready-->>DB: Promise resolves/rejects
    DB->>App: new() resolves/rejects

    App->>DB: query(sql, params)
    DB->>MainW: postMessage { type: "execute-query", requestId, ... }
    MainW->>CoreW: deliver execute-query
    CoreW-->>MainW: postMessage { type: "query-result", requestId, result/error }
    MainW->>DB: resolve/reject pending promise
    DB->>App: query result or mapped InitializationPending error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Areas to focus on:

  • Leader probing, race conditions, and follower timeout handling (packages/sqlite-web-core/src/coordination.rs).
  • ReadySignal Promise lifecycle and correct clearing/invocation of resolve/reject (packages/sqlite-web/src/ready.rs, packages/sqlite-web/src/db.rs).
  • JS <-> Rust interop: param normalization (BigInt/blob/base64) and rejection semantics for NaN/Infinity (packages/sqlite-web/src/params.rs).
  • Structured error payload shape and consistent serialization across worker ↔ main boundaries (packages/sqlite-web/src/messages.rs, packages/sqlite-web-core/src/messages.rs, packages/sqlite-web/src/worker.rs).
  • Timing-sensitive tests and postMessage spies for stability (packages/sqlite-web/src/tests.rs, svelte-test fixtures).

Possibly related PRs

Suggested reviewers

  • hardyjosh
  • 0xgleb

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 49.18% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: introducing timeout logic for followers waiting for a leader, with probing, state tracking, and deadline enforcement across the core worker coordination and database modules.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch query-timeout

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 578cd48 and 345d18f.

⛔ Files ignored due to path filters (1)
  • svelte-test/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • packages/sqlite-web/src/db.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/messages.rs : Use structured message types for worker communication as defined in messages.rs
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/worker.rs : Keep worker.rs as the main worker entry point invoked by worker_main()
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/worker_template.rs : Ensure the worker JavaScript generated by worker_template.rs embeds the WASM (base64) and does not fetch external WASM files
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Maintain self-contained workers with no external WASM file dependencies across the project
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 9
File: packages/sqlite-web-core/src/coordination.rs:52-65
Timestamp: 2025-09-15T06:11:31.781Z
Learning: In packages/sqlite-web-core/src/coordination.rs, the pattern of using `db.borrow_mut().take()` followed by async database operations and then putting the database back with `*db.borrow_mut() = Some(database)` is safe in their use case and doesn't cause concurrent access issues or "Database not initialized" errors.
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/lib.rs : Expose an async, promise-based query interface from the SQLiteWasmDatabase public API
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/lib.rs : Expose an async, promise-based query interface from the SQLiteWasmDatabase public API

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/worker_template.rs : Ensure the worker JavaScript generated by worker_template.rs embeds the WASM (base64) and does not fetch external WASM files

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/worker.rs : Keep worker.rs as the main worker entry point invoked by worker_main()

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/database_functions.rs : Integrate and expose rain.math.float-backed custom database functions for SQLite queries

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/messages.rs : Use structured message types for worker communication as defined in messages.rs

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-09-15T06:11:31.781Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 9
File: packages/sqlite-web-core/src/coordination.rs:52-65
Timestamp: 2025-09-15T06:11:31.781Z
Learning: In packages/sqlite-web-core/src/coordination.rs, the pattern of using `db.borrow_mut().take()` followed by async database operations and then putting the database back with `*db.borrow_mut() = Some(database)` is safe in their use case and doesn't cause concurrent access issues or "Database not initialized" errors.

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-10-20T12:24:07.874Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 19
File: packages/sqlite-web-core/src/database.rs:122-157
Timestamp: 2025-10-20T12:24:07.874Z
Learning: In packages/sqlite-web-core/src/database.rs, named parameters (:name, name, $name) are intentionally not supported for SQL parameter binding. Only plain '?' and numbered '?N' placeholders are supported.

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/embedded_worker.js : Do not manually edit embedded_worker.js; it is generated by the build and should be treated as read-only

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-09-19T07:06:20.173Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 14
File: svelte-test/tests/database-functions/float-is-zero.test.ts:39-57
Timestamp: 2025-09-19T07:06:20.173Z
Learning: PRAGMA function_list is not available in the WASM SQLite test environment used by svelte-test, so availability testing should rely on direct function calls rather than PRAGMA queries.

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-08-27T05:55:40.481Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 5
File: packages/sqlite-web-core/src/database_functions/bigint_sum.rs:76-93
Timestamp: 2025-08-27T05:55:40.481Z
Learning: In the sqlite-web-core codebase, for SQLite aggregate function context initialization, the maintainer prefers using byte-scanning to detect zero-initialized memory rather than using explicit initialization flags or Option wrappers.

Applied to files:

  • packages/sqlite-web/src/db.rs
🧬 Code graph analysis (1)
packages/sqlite-web/src/db.rs (6)
packages/sqlite-web/src/params.rs (1)
  • normalize_params_js (7-14)
packages/sqlite-web/src/utils.rs (1)
  • describe_js_value (3-14)
packages/sqlite-web/src/worker.rs (2)
  • create_worker_from_code (14-26)
  • install_onmessage_handler (28-45)
packages/sqlite-web/src/worker_template.rs (1)
  • generate_self_contained_worker (4-14)
packages/sqlite-web/src/ready.rs (1)
  • new (25-40)
packages/sqlite-web/src/errors.rs (3)
  • from (18-20)
  • from (24-26)
  • from (30-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5da26c5 and d89d90f.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • svelte-test/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (18)
  • packages/sqlite-web-core/src/coordination.rs (14 hunks)
  • packages/sqlite-web-core/src/messages.rs (2 hunks)
  • packages/sqlite-web-core/src/worker.rs (2 hunks)
  • packages/sqlite-web/src/db.rs (1 hunks)
  • packages/sqlite-web/src/errors.rs (1 hunks)
  • packages/sqlite-web/src/lib.rs (1 hunks)
  • packages/sqlite-web/src/params.rs (1 hunks)
  • packages/sqlite-web/src/ready.rs (1 hunks)
  • packages/sqlite-web/src/tests.rs (1 hunks)
  • packages/sqlite-web/src/utils.rs (1 hunks)
  • packages/sqlite-web/src/worker.rs (1 hunks)
  • packages/sqlite-web/src/worker_template.rs (1 hunks)
  • pkg/package.json (1 hunks)
  • scripts/local-bundle.sh (0 hunks)
  • svelte-test/package.json (1 hunks)
  • svelte-test/src/routes/+page.svelte (1 hunks)
  • svelte-test/src/routes/sql/+page.svelte (1 hunks)
  • svelte-test/tests/fixtures/test-helpers.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • scripts/local-bundle.sh
🧰 Additional context used
📓 Path-based instructions (3)
packages/sqlite-web-core/src/messages.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Use structured message types for worker communication as defined in messages.rs

Files:

  • packages/sqlite-web-core/src/messages.rs
svelte-test/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

In the Svelte test app, depend on the sqlite-web package via the locally packed tarball produced by npm pack

Files:

  • svelte-test/package.json
packages/sqlite-web-core/src/worker.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Keep worker.rs as the main worker entry point invoked by worker_main()

Files:

  • packages/sqlite-web-core/src/worker.rs
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/messages.rs : Use structured message types for worker communication as defined in messages.rs
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/worker.rs : Keep worker.rs as the main worker entry point invoked by worker_main()
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/worker_template.rs : Ensure the worker JavaScript generated by worker_template.rs embeds the WASM (base64) and does not fetch external WASM files
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 9
File: packages/sqlite-web-core/src/coordination.rs:52-65
Timestamp: 2025-09-15T06:11:31.781Z
Learning: In packages/sqlite-web-core/src/coordination.rs, the pattern of using `db.borrow_mut().take()` followed by async database operations and then putting the database back with `*db.borrow_mut() = Some(database)` is safe in their use case and doesn't cause concurrent access issues or "Database not initialized" errors.
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/lib.rs : Expose an async, promise-based query interface from the SQLiteWasmDatabase public API
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/database_functions.rs : Integrate and expose rain.math.float-backed custom database functions for SQLite queries

Applied to files:

  • packages/sqlite-web/src/utils.rs
  • packages/sqlite-web/src/errors.rs
  • packages/sqlite-web/src/params.rs
  • packages/sqlite-web/src/worker_template.rs
  • packages/sqlite-web/src/tests.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/coordination.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/worker_template.rs : Ensure the worker JavaScript generated by worker_template.rs embeds the WASM (base64) and does not fetch external WASM files

Applied to files:

  • packages/sqlite-web/src/utils.rs
  • packages/sqlite-web/src/errors.rs
  • packages/sqlite-web/src/ready.rs
  • svelte-test/src/routes/sql/+page.svelte
  • packages/sqlite-web-core/src/worker.rs
  • packages/sqlite-web/src/params.rs
  • packages/sqlite-web/src/worker_template.rs
  • svelte-test/src/routes/+page.svelte
  • packages/sqlite-web/src/tests.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/coordination.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/lib.rs : Expose an async, promise-based query interface from the SQLiteWasmDatabase public API

Applied to files:

  • packages/sqlite-web/src/utils.rs
  • packages/sqlite-web/src/errors.rs
  • packages/sqlite-web/src/ready.rs
  • svelte-test/src/routes/sql/+page.svelte
  • svelte-test/tests/fixtures/test-helpers.ts
  • packages/sqlite-web/src/params.rs
  • packages/sqlite-web/src/worker_template.rs
  • svelte-test/src/routes/+page.svelte
  • packages/sqlite-web/src/tests.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/coordination.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/messages.rs : Use structured message types for worker communication as defined in messages.rs

Applied to files:

  • packages/sqlite-web/src/utils.rs
  • packages/sqlite-web-core/src/messages.rs
  • packages/sqlite-web/src/errors.rs
  • packages/sqlite-web/src/ready.rs
  • svelte-test/src/routes/sql/+page.svelte
  • packages/sqlite-web-core/src/worker.rs
  • packages/sqlite-web/src/params.rs
  • packages/sqlite-web/src/worker_template.rs
  • svelte-test/src/routes/+page.svelte
  • packages/sqlite-web/src/tests.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/coordination.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to svelte-test/package.json : In the Svelte test app, depend on the sqlite-web package via the locally packed tarball produced by npm pack

Applied to files:

  • svelte-test/package.json
  • svelte-test/src/routes/sql/+page.svelte
  • svelte-test/tests/fixtures/test-helpers.ts
  • svelte-test/src/routes/+page.svelte
  • packages/sqlite-web/src/tests.rs
📚 Learning: 2025-08-27T05:59:04.254Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 5
File: svelte-test/tests/database-functions/bigint-sum.test.ts:2-7
Timestamp: 2025-08-27T05:59:04.254Z
Learning: In the sqlite-web repository, the user prefers to keep .js extensions when importing TypeScript files in test files, even in Vitest environments. This is acceptable and should not be flagged as an issue.

Applied to files:

  • svelte-test/package.json
  • svelte-test/src/routes/sql/+page.svelte
  • svelte-test/tests/fixtures/test-helpers.ts
📚 Learning: 2025-08-21T15:09:22.737Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 2
File: flake.nix:59-68
Timestamp: 2025-08-21T15:09:22.737Z
Learning: In the sqlite-web project, the build-submodules task in flake.nix successfully builds the lib/rain.math.float submodule with `forge build` even if foundry.toml is not immediately visible in the expected location. The build process works as intended according to the project maintainer.

Applied to files:

  • svelte-test/package.json
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/worker.rs : Keep worker.rs as the main worker entry point invoked by worker_main()

Applied to files:

  • packages/sqlite-web/src/errors.rs
  • packages/sqlite-web/src/ready.rs
  • svelte-test/src/routes/sql/+page.svelte
  • packages/sqlite-web-core/src/worker.rs
  • packages/sqlite-web/src/params.rs
  • packages/sqlite-web/src/worker_template.rs
  • svelte-test/src/routes/+page.svelte
  • packages/sqlite-web/src/tests.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/coordination.rs
📚 Learning: 2025-09-19T07:06:20.173Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 14
File: svelte-test/tests/database-functions/float-is-zero.test.ts:39-57
Timestamp: 2025-09-19T07:06:20.173Z
Learning: PRAGMA function_list is not available in the WASM SQLite test environment used by svelte-test, so availability testing should rely on direct function calls rather than PRAGMA queries.

Applied to files:

  • packages/sqlite-web/src/errors.rs
  • svelte-test/src/routes/sql/+page.svelte
  • svelte-test/tests/fixtures/test-helpers.ts
  • packages/sqlite-web/src/params.rs
  • svelte-test/src/routes/+page.svelte
  • packages/sqlite-web/src/tests.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
📚 Learning: 2025-09-15T06:11:31.781Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 9
File: packages/sqlite-web-core/src/coordination.rs:52-65
Timestamp: 2025-09-15T06:11:31.781Z
Learning: In packages/sqlite-web-core/src/coordination.rs, the pattern of using `db.borrow_mut().take()` followed by async database operations and then putting the database back with `*db.borrow_mut() = Some(database)` is safe in their use case and doesn't cause concurrent access issues or "Database not initialized" errors.

Applied to files:

  • packages/sqlite-web/src/ready.rs
  • svelte-test/src/routes/sql/+page.svelte
  • packages/sqlite-web/src/worker_template.rs
  • svelte-test/src/routes/+page.svelte
  • packages/sqlite-web/src/tests.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/coordination.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/embedded_worker.js : Do not manually edit embedded_worker.js; it is generated by the build and should be treated as read-only

Applied to files:

  • svelte-test/src/routes/sql/+page.svelte
  • packages/sqlite-web/src/worker_template.rs
  • svelte-test/src/routes/+page.svelte
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/worker.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Maintain self-contained workers with no external WASM file dependencies across the project

Applied to files:

  • svelte-test/src/routes/sql/+page.svelte
  • packages/sqlite-web/src/worker_template.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/worker.rs
📚 Learning: 2025-09-15T10:01:17.743Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 12
File: svelte-test/tests/fixtures/test-helpers.ts:11-11
Timestamp: 2025-09-15T10:01:17.743Z
Learning: In the sqlite-web project, test database names in createTestDatabase function do not need timestamp suffixes for uniqueness. The maintainer has confirmed that test isolation via unique naming is not required.

Applied to files:

  • svelte-test/tests/fixtures/test-helpers.ts
📚 Learning: 2025-09-17T08:04:44.062Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 6
File: svelte-test/tests/database-functions/float-sum.test.ts:78-86
Timestamp: 2025-09-17T08:04:44.062Z
Learning: In svelte-test/tests/database-functions/float-sum.test.ts, the schema defines `amount TEXT NOT NULL` but the NULL value handling tests attempt to insert NULL values, creating a constraint violation that prevents the tests from passing.

Applied to files:

  • svelte-test/tests/fixtures/test-helpers.ts
  • packages/sqlite-web/src/lib.rs
📚 Learning: 2025-10-20T12:24:07.874Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 19
File: packages/sqlite-web-core/src/database.rs:122-157
Timestamp: 2025-10-20T12:24:07.874Z
Learning: In packages/sqlite-web-core/src/database.rs, named parameters (:name, name, $name) are intentionally not supported for SQL parameter binding. Only plain '?' and numbered '?N' placeholders are supported.

Applied to files:

  • packages/sqlite-web/src/params.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
📚 Learning: 2025-09-17T17:44:54.855Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 15
File: svelte-test/tests/integration/error-handling.test.ts:418-434
Timestamp: 2025-09-17T17:44:54.855Z
Learning: In the sqlite-web test harness, parameter binding is not available for the db.query() method, so string interpolation with manual SQL escaping using value.replace(/'/g, "''") is the necessary approach for handling special characters in test data.

Applied to files:

  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
🧬 Code graph analysis (8)
packages/sqlite-web/src/errors.rs (3)
packages/sqlite-web/src/worker.rs (1)
  • serde_wasm_bindgen (58-58)
packages/sqlite-web/src/db.rs (1)
  • new (42-52)
packages/sqlite-web/src/ready.rs (1)
  • new (25-40)
packages/sqlite-web/src/ready.rs (2)
packages/sqlite-web/src/db.rs (1)
  • new (42-52)
packages/sqlite-web/src/errors.rs (3)
  • from (18-20)
  • from (24-26)
  • from (30-35)
packages/sqlite-web-core/src/worker.rs (1)
packages/sqlite-web-core/src/coordination.rs (1)
  • new (72-121)
packages/sqlite-web/src/params.rs (1)
packages/sqlite-web/src/errors.rs (3)
  • from (18-20)
  • from (24-26)
  • from (30-35)
packages/sqlite-web/src/tests.rs (7)
packages/sqlite-web/src/worker.rs (2)
  • handle_worker_control_message (57-74)
  • serde_wasm_bindgen (58-58)
packages/sqlite-web/src/worker_template.rs (1)
  • generate_self_contained_worker (4-14)
packages/sqlite-web-core/src/coordination.rs (1)
  • js_sys (400-401)
packages/sqlite-web/src/db.rs (1)
  • new (42-52)
packages/sqlite-web/src/ready.rs (2)
  • new (25-40)
  • current_state (42-44)
packages/sqlite-web/src/errors.rs (3)
  • from (18-20)
  • from (24-26)
  • from (30-35)
packages/sqlite-web/src/params.rs (3)
  • v (32-32)
  • v (35-35)
  • v (38-38)
packages/sqlite-web/src/db.rs (6)
packages/sqlite-web/src/params.rs (1)
  • normalize_params_js (7-14)
packages/sqlite-web/src/utils.rs (1)
  • describe_js_value (3-14)
packages/sqlite-web/src/worker.rs (2)
  • create_worker_from_code (15-27)
  • install_onmessage_handler (29-46)
packages/sqlite-web/src/worker_template.rs (1)
  • generate_self_contained_worker (4-14)
packages/sqlite-web/src/ready.rs (1)
  • new (25-40)
packages/sqlite-web/src/errors.rs (3)
  • from (18-20)
  • from (24-26)
  • from (30-35)
packages/sqlite-web/src/worker.rs (2)
packages/sqlite-web/src/utils.rs (1)
  • describe_js_value (3-14)
packages/sqlite-web/src/ready.rs (2)
  • new (25-40)
  • current_state (42-44)
packages/sqlite-web-core/src/coordination.rs (2)
packages/sqlite-web-core/src/util.rs (3)
  • js_value_to_string (39-60)
  • set_js_property (29-37)
  • sanitize_identifier (5-19)
packages/sqlite-web-core/src/worker.rs (1)
  • send_worker_error_message (19-30)
🔇 Additional comments (16)
packages/sqlite-web-core/src/messages.rs (1)

29-33: Leader ping variant matches the schema.

Serde rename keeps the payload aligned with existing channel events, and the roundtrip test locks the JSON shape.

packages/sqlite-web/src/worker_template.rs (2)

7-10: Timeout constant injection looks solid.

Encoding the DB name first and then defining __SQLITE_FOLLOWER_TIMEOUT_MS keeps the worker bootstrap self-contained while giving followers the shared budget.


23-44: WASM tests cover the new worker prefix.

These browser tests pin the prefix values and ensure the embedded worker stays untouched, catching regressions early.

packages/sqlite-web/src/utils.rs (2)

3-14: Helper captures the common JS value cases cleanly.

String/number fast paths and debug fallback give concise diagnostics without extra allocations.


23-42: Nice WASM-side assertions.

The browser tests walk through strings, integers, floats, and objects, so the helper’s behavior is fully exercised.

packages/sqlite-web/src/lib.rs (1)

9-10: Re-exports keep the public API intact.

Pulling SQLiteWasmDatabase and SQLiteWasmDatabaseError from the new modules maintains existing consumers while letting the internals refactor freely.

packages/sqlite-web/src/errors.rs (2)

5-35: Error type covers the wasm surface area.

Variant set lines up with serde, JS interop, and initialization flows, and the conversions give consistent messages back to the host.


46-87: Conversion tests are thorough.

Round-tripping through JsValue and WasmEncodedError plus the serde variant check should catch regressions in the glue code.

packages/sqlite-web/src/db.rs (8)

1-17: LGTM!

The imports are well-organized and all necessary for the WASM database interface implementation.


19-25: LGTM!

The struct design appropriately uses interior mutability patterns to manage worker communication state and track pending queries.


42-52: LGTM!

The constructor properly validates input before constructing resources and correctly separates construction from readiness synchronization.


54-70: LGTM!

The internal constructor properly initializes all state and wires up worker communication. Starting request_id at 1 is correct (avoids 0).


72-75: LGTM!

The parameter normalization properly converts Rust Option to JS undefined and delegates to the dedicated params module.


120-122: LGTM!

The early check for initialization failure prevents unnecessary work and provides a clear error to the caller.


132-137: LGTM!

The request ID generation with wrapping and skipping 0 is correct. While theoretically IDs could collide after wrapping (requiring billions of concurrent queries), this is not a practical concern.


187-274: LGTM!

The tests provide good coverage of parameter normalization edge cases and input validation. The tests correctly verify BigInt and ArrayBuffer encoding formats.

Comment on lines +27 to +36
impl Serialize for SQLiteWasmDatabase {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let state = serializer.serialize_struct("SQLiteWasmDatabase", 0)?;
state.end()
}
}
Copy link

@coderabbitai coderabbitai bot Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider documenting why Serialize is empty.

The empty Serialize implementation is valid but may confuse readers since it discards all state. Consider adding a comment explaining that the worker and callbacks cannot be serialized and this is intentionally minimal.

🤖 Prompt for AI Agents
In packages/sqlite-web/src/db.rs around lines 27 to 36, the custom Serialize
impl returns an empty struct which silently discards all state; add a short
comment above the impl (or inside the method) stating that this is intentional
because the database contains non-serializable runtime state (worker handles,
callbacks, threads, etc.) and therefore must be serialized as an empty
placeholder, so future readers won’t think this is a bug. Ensure the comment
briefly lists the non-serializable pieces and that any future state intended for
persistence must be explicitly added and documented.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@findolor Understood, no problem! 👍


🧠 Learnings used
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/lib.rs : Expose an async, promise-based query interface from the SQLiteWasmDatabase public API

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/worker.rs : Keep worker.rs as the main worker entry point invoked by worker_main()

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/worker_template.rs : Ensure the worker JavaScript generated by worker_template.rs embeds the WASM (base64) and does not fetch external WASM files

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/messages.rs : Use structured message types for worker communication as defined in messages.rs

Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 9
File: packages/sqlite-web-core/src/coordination.rs:52-65
Timestamp: 2025-09-15T06:11:31.781Z
Learning: In packages/sqlite-web-core/src/coordination.rs, the pattern of using `db.borrow_mut().take()` followed by async database operations and then putting the database back with `*db.borrow_mut() = Some(database)` is safe in their use case and doesn't cause concurrent access issues or "Database not initialized" errors.

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/database_functions.rs : Integrate and expose rain.math.float-backed custom database functions for SQLite queries

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/embedded_worker.js : Do not manually edit embedded_worker.js; it is generated by the build and should be treated as read-only

Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 19
File: packages/sqlite-web-core/src/database.rs:122-157
Timestamp: 2025-10-20T12:24:07.874Z
Learning: In packages/sqlite-web-core/src/database.rs, named parameters (:name, name, $name) are intentionally not supported for SQL parameter binding. Only plain '?' and numbered '?N' placeholders are supported.

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Maintain self-contained workers with no external WASM file dependencies across the project

Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 14
File: svelte-test/tests/database-functions/float-is-zero.test.ts:39-57
Timestamp: 2025-09-19T07:06:20.173Z
Learning: PRAGMA function_list is not available in the WASM SQLite test environment used by svelte-test, so availability testing should rely on direct function calls rather than PRAGMA queries.

Comment on lines 110 to 184
pub async fn query(
&self,
sql: &str,
params: Option<Array>,
) -> Result<String, SQLiteWasmDatabaseError> {
let worker = &self.worker;
let pending_queries = Rc::clone(&self.pending_queries);
let sql = sql.to_string();
let params_array = Self::normalize_params(params)?;

if let InitializationState::Failed(reason) = self.ready_signal.current_state() {
return Err(SQLiteWasmDatabaseError::InitializationFailed(reason));
}

let message = js_sys::Object::new();
js_sys::Reflect::set(
&message,
&JsValue::from_str("type"),
&JsValue::from_str("execute-query"),
)
.map_err(SQLiteWasmDatabaseError::JsError)?;

let request_id = {
let mut n = self.next_request_id.borrow_mut();
let id = *n;
*n = n.wrapping_add(1).max(1);
id
};
js_sys::Reflect::set(
&message,
&JsValue::from_str("requestId"),
&JsValue::from_f64(request_id as f64),
)
.map_err(SQLiteWasmDatabaseError::JsError)?;
js_sys::Reflect::set(
&message,
&JsValue::from_str("sql"),
&JsValue::from_str(&sql),
)
.map_err(SQLiteWasmDatabaseError::JsError)?;
if params_array.length() > 0 {
let params_js = JsValue::from(params_array.clone());
js_sys::Reflect::set(&message, &JsValue::from_str("params"), &params_js)
.map_err(SQLiteWasmDatabaseError::JsError)?;
}

let rid_for_insert = request_id;
let promise =
js_sys::Promise::new(&mut |resolve, reject| match worker.post_message(&message) {
Ok(()) => {
pending_queries
.borrow_mut()
.insert(rid_for_insert, (resolve, reject));
}
Err(err) => {
let _ = reject.call1(&JsValue::NULL, &err);
}
});

let result = match JsFuture::from(promise).await {
Ok(value) => value,
Err(err) => {
if err
.as_string()
.as_deref()
.map(|s| s == "InitializationPending")
.unwrap_or(false)
{
return Err(SQLiteWasmDatabaseError::InitializationPending);
}
return Err(SQLiteWasmDatabaseError::JsError(err));
}
};
Ok(result.as_string().unwrap_or_else(|| format!("{result:?}")))
}
Copy link

@coderabbitai coderabbitai bot Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Query execution logic is correct; consider future resilience improvements.

The query method correctly constructs messages, posts them to the worker, and awaits results. However, consider the following optional improvements for production resilience:

  1. Per-query timeout: Queries currently wait indefinitely for the worker. A configurable timeout per query would prevent indefinite hangs.
  2. Pending queries cleanup: If the worker crashes or queries are abandoned, entries in pending_queries are never removed, leading to a memory leak.
  3. Worker lifecycle management: Consider adding a close() or terminate() method to explicitly shut down the worker when the database is no longer needed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@findolor Understood, thanks for the clarification!


🧠 Learnings used
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/lib.rs : Expose an async, promise-based query interface from the SQLiteWasmDatabase public API

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/worker.rs : Keep worker.rs as the main worker entry point invoked by worker_main()

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/worker_template.rs : Ensure the worker JavaScript generated by worker_template.rs embeds the WASM (base64) and does not fetch external WASM files

Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 9
File: packages/sqlite-web-core/src/coordination.rs:52-65
Timestamp: 2025-09-15T06:11:31.781Z
Learning: In packages/sqlite-web-core/src/coordination.rs, the pattern of using `db.borrow_mut().take()` followed by async database operations and then putting the database back with `*db.borrow_mut() = Some(database)` is safe in their use case and doesn't cause concurrent access issues or "Database not initialized" errors.

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/messages.rs : Use structured message types for worker communication as defined in messages.rs

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/database_functions.rs : Integrate and expose rain.math.float-backed custom database functions for SQLite queries

Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 19
File: packages/sqlite-web-core/src/database.rs:122-157
Timestamp: 2025-10-20T12:24:07.874Z
Learning: In packages/sqlite-web-core/src/database.rs, named parameters (:name, name, $name) are intentionally not supported for SQL parameter binding. Only plain '?' and numbered '?N' placeholders are supported.

Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 15
File: svelte-test/tests/integration/error-handling.test.ts:418-434
Timestamp: 2025-09-17T17:44:54.855Z
Learning: In the sqlite-web test harness, parameter binding is not available for the db.query() method, so string interpolation with manual SQL escaping using value.replace(/'/g, "''") is the necessary approach for handling special characters in test data.

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/embedded_worker.js : Do not manually edit embedded_worker.js; it is generated by the build and should be treated as read-only

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Maintain self-contained workers with no external WASM file dependencies across the project

Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 14
File: svelte-test/tests/database-functions/float-is-zero.test.ts:39-57
Timestamp: 2025-09-19T07:06:20.173Z
Learning: PRAGMA function_list is not available in the WASM SQLite test environment used by svelte-test, so availability testing should rely on direct function calls rather than PRAGMA queries.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d89d90f and 9e4cfdd.

⛔ Files ignored due to path filters (1)
  • svelte-test/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • packages/sqlite-web-core/src/coordination.rs (13 hunks)
  • packages/sqlite-web-core/src/messages.rs (5 hunks)
  • packages/sqlite-web-core/src/worker.rs (5 hunks)
  • packages/sqlite-web/src/db.rs (1 hunks)
  • packages/sqlite-web/src/lib.rs (1 hunks)
  • packages/sqlite-web/src/messages.rs (1 hunks)
  • packages/sqlite-web/src/ready.rs (1 hunks)
  • packages/sqlite-web/src/worker.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
packages/sqlite-web-core/src/worker.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Keep worker.rs as the main worker entry point invoked by worker_main()

Files:

  • packages/sqlite-web-core/src/worker.rs
packages/sqlite-web-core/src/messages.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Use structured message types for worker communication as defined in messages.rs

Files:

  • packages/sqlite-web-core/src/messages.rs
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Maintain self-contained workers with no external WASM file dependencies across the project
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/worker_template.rs : Ensure the worker JavaScript generated by worker_template.rs embeds the WASM (base64) and does not fetch external WASM files
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/worker.rs : Keep worker.rs as the main worker entry point invoked by worker_main()
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/messages.rs : Use structured message types for worker communication as defined in messages.rs
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/embedded_worker.js : Do not manually edit embedded_worker.js; it is generated by the build and should be treated as read-only
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/worker_template.rs : Ensure the worker JavaScript generated by worker_template.rs embeds the WASM (base64) and does not fetch external WASM files

Applied to files:

  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web/src/ready.rs
  • packages/sqlite-web-core/src/coordination.rs
  • packages/sqlite-web/src/messages.rs
  • packages/sqlite-web-core/src/worker.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/messages.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/worker.rs : Keep worker.rs as the main worker entry point invoked by worker_main()

Applied to files:

  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web/src/ready.rs
  • packages/sqlite-web-core/src/coordination.rs
  • packages/sqlite-web/src/messages.rs
  • packages/sqlite-web-core/src/worker.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/messages.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/messages.rs : Use structured message types for worker communication as defined in messages.rs

Applied to files:

  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web/src/ready.rs
  • packages/sqlite-web-core/src/coordination.rs
  • packages/sqlite-web/src/messages.rs
  • packages/sqlite-web-core/src/worker.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/messages.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Maintain self-contained workers with no external WASM file dependencies across the project

Applied to files:

  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web-core/src/coordination.rs
  • packages/sqlite-web-core/src/worker.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/embedded_worker.js : Do not manually edit embedded_worker.js; it is generated by the build and should be treated as read-only

Applied to files:

  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web-core/src/coordination.rs
  • packages/sqlite-web/src/messages.rs
  • packages/sqlite-web-core/src/worker.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web-core/src/messages.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/lib.rs : Expose an async, promise-based query interface from the SQLiteWasmDatabase public API

Applied to files:

  • packages/sqlite-web/src/worker.rs
  • packages/sqlite-web/src/ready.rs
  • packages/sqlite-web-core/src/coordination.rs
  • packages/sqlite-web/src/messages.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
  • packages/sqlite-web-core/src/messages.rs
📚 Learning: 2025-09-15T06:11:31.781Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 9
File: packages/sqlite-web-core/src/coordination.rs:52-65
Timestamp: 2025-09-15T06:11:31.781Z
Learning: In packages/sqlite-web-core/src/coordination.rs, the pattern of using `db.borrow_mut().take()` followed by async database operations and then putting the database back with `*db.borrow_mut() = Some(database)` is safe in their use case and doesn't cause concurrent access issues or "Database not initialized" errors.

Applied to files:

  • packages/sqlite-web/src/ready.rs
  • packages/sqlite-web-core/src/coordination.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
📚 Learning: 2025-09-17T06:55:20.178Z
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/database_functions.rs : Integrate and expose rain.math.float-backed custom database functions for SQLite queries

Applied to files:

  • packages/sqlite-web-core/src/coordination.rs
  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
📚 Learning: 2025-10-20T12:24:07.874Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 19
File: packages/sqlite-web-core/src/database.rs:122-157
Timestamp: 2025-10-20T12:24:07.874Z
Learning: In packages/sqlite-web-core/src/database.rs, named parameters (:name, name, $name) are intentionally not supported for SQL parameter binding. Only plain '?' and numbered '?N' placeholders are supported.

Applied to files:

  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
📚 Learning: 2025-09-19T07:06:20.173Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 14
File: svelte-test/tests/database-functions/float-is-zero.test.ts:39-57
Timestamp: 2025-09-19T07:06:20.173Z
Learning: PRAGMA function_list is not available in the WASM SQLite test environment used by svelte-test, so availability testing should rely on direct function calls rather than PRAGMA queries.

Applied to files:

  • packages/sqlite-web/src/db.rs
  • packages/sqlite-web/src/lib.rs
📚 Learning: 2025-08-27T05:55:40.481Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 5
File: packages/sqlite-web-core/src/database_functions/bigint_sum.rs:76-93
Timestamp: 2025-08-27T05:55:40.481Z
Learning: In the sqlite-web-core codebase, for SQLite aggregate function context initialization, the maintainer prefers using byte-scanning to detect zero-initialized memory rather than using explicit initialization flags or Option wrappers.

Applied to files:

  • packages/sqlite-web/src/db.rs
📚 Learning: 2025-09-17T17:44:54.855Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 15
File: svelte-test/tests/integration/error-handling.test.ts:418-434
Timestamp: 2025-09-17T17:44:54.855Z
Learning: In the sqlite-web test harness, parameter binding is not available for the db.query() method, so string interpolation with manual SQL escaping using value.replace(/'/g, "''") is the necessary approach for handling special characters in test data.

Applied to files:

  • packages/sqlite-web/src/lib.rs
📚 Learning: 2025-09-17T08:04:44.062Z
Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 6
File: svelte-test/tests/database-functions/float-sum.test.ts:78-86
Timestamp: 2025-09-17T08:04:44.062Z
Learning: In svelte-test/tests/database-functions/float-sum.test.ts, the schema defines `amount TEXT NOT NULL` but the NULL value handling tests attempt to insert NULL values, creating a constraint violation that prevents the tests from passing.

Applied to files:

  • packages/sqlite-web/src/lib.rs
🧬 Code graph analysis (5)
packages/sqlite-web/src/worker.rs (2)
packages/sqlite-web/src/utils.rs (1)
  • describe_js_value (3-14)
packages/sqlite-web/src/ready.rs (2)
  • new (25-40)
  • current_state (42-44)
packages/sqlite-web/src/ready.rs (3)
packages/sqlite-web-core/src/coordination.rs (2)
  • js_sys (411-412)
  • new (72-121)
packages/sqlite-web/src/db.rs (1)
  • new (43-53)
packages/sqlite-web/src/errors.rs (3)
  • from (18-20)
  • from (24-26)
  • from (30-35)
packages/sqlite-web-core/src/coordination.rs (2)
packages/sqlite-web-core/src/util.rs (2)
  • js_value_to_string (39-60)
  • set_js_property (29-37)
packages/sqlite-web-core/src/worker.rs (1)
  • send_worker_error_message (21-32)
packages/sqlite-web-core/src/worker.rs (2)
packages/sqlite-web-core/src/coordination.rs (2)
  • js_sys (411-412)
  • new (72-121)
packages/sqlite-web-core/src/util.rs (1)
  • set_js_property (29-37)
packages/sqlite-web/src/db.rs (6)
packages/sqlite-web/src/params.rs (1)
  • normalize_params_js (7-14)
packages/sqlite-web/src/utils.rs (1)
  • describe_js_value (3-14)
packages/sqlite-web/src/worker.rs (2)
  • create_worker_from_code (14-26)
  • install_onmessage_handler (28-45)
packages/sqlite-web/src/worker_template.rs (1)
  • generate_self_contained_worker (4-14)
packages/sqlite-web/src/ready.rs (1)
  • new (25-40)
packages/sqlite-web/src/errors.rs (3)
  • from (18-20)
  • from (24-26)
  • from (30-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test
  • GitHub Check: test
🔇 Additional comments (13)
packages/sqlite-web/src/lib.rs (1)

1-14: LGTM - Clean modularization.

The refactoring organizes the codebase into well-defined modules while preserving the public API surface through re-exports. The module boundaries are clear and follow Rust conventions.

packages/sqlite-web-core/src/worker.rs (5)

11-13: LGTM - Import aligns with structured error handling.

The addition of WorkerMessage and error type constants from crate::messages supports the new structured error payload system introduced in this PR.


50-64: LGTM - Well-structured error helper.

The make_structured_error function correctly creates typed error objects that align with the WorkerErrorPayload structure. The conditional logic appropriately distinguishes between initialization-pending and generic error types.


84-85: LGTM - Upgraded to structured error format.

The query result error handling now uses make_structured_error, ensuring error responses include both type and message fields. This improves error categorization and client-side error handling.


149-155: LGTM - Enhanced initialization error visibility.

Adding inspect_err to propagate initialization errors via send_worker_error improves debugging without altering the error propagation flow. Errors are now visible to the host during worker setup failures.


169-169: LGTM - Leader probe initialization.

The call to state.start_leader_probe() implements the follower timeout feature described in the PR objectives, enabling workers to detect leaders quickly and fail fast when deadlines expire.

packages/sqlite-web-core/src/messages.rs (4)

4-5: LGTM - Error type constants for structured messaging.

These constants define the error type discriminators used in WorkerErrorPayload, enabling typed error handling across the worker communication layer.


7-14: LGTM - Well-designed error payload structure.

WorkerErrorPayload provides a typed, serializable error structure with appropriate serde attributes for JavaScript interop. The optional message field with skip_serializing_if keeps payloads concise when messages aren't needed.


41-45: LGTM - Leader discovery message type.

The LeaderPing variant enables the follower timeout mechanism by allowing workers to probe for leader presence. The structure follows established patterns in the ChannelMessage enum.


72-72: LGTM - Upgraded to structured error payload.

Changing the error field from Option<String> to Option<WorkerErrorPayload> enables typed error handling and aligns with the broader structured messaging improvements in this PR.

packages/sqlite-web/src/ready.rs (3)

9-40: LGTM - Sound readiness coordination design.

The InitializationState enum and ReadySignal structure provide a clear state machine for worker readiness. The use of Rc<RefCell<>> for interior mutability is appropriate for single-threaded WASM contexts, and the promise-based API integrates well with JavaScript async patterns.


54-75: LGTM - Past review concern resolved.

The mark_ready implementation now correctly prevents overriding Failed states by checking the state and returning early (Line 59). The transition and handler cleanup only occur when transitioning from Pending to Ready, ensuring failure states remain terminal as intended.


77-102: LGTM - Correct failure handling and promise creation.

The mark_failed method properly transitions to the Failed state, invokes the reject callback with the reason, and cleans up handlers. The create_ready_promise helper correctly captures resolve/reject functions into the provided cells. The implementation is sound and well-tested.

Comment on lines +1 to +3
#[cfg(all(test, target_family = "wasm"))]
pub const WORKER_ERROR_TYPE_GENERIC: &str = "WorkerError";
pub const WORKER_ERROR_TYPE_INITIALIZATION_PENDING: &str = "InitializationPending";
Copy link

@coderabbitai coderabbitai bot Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix cfg attribute scope - only the first constant is gated.

The #[cfg(all(test, target_family = "wasm"))] attribute on Line 1 applies only to Line 2 (WORKER_ERROR_TYPE_GENERIC). Line 3 (WORKER_ERROR_TYPE_INITIALIZATION_PENDING) is unconditionally compiled, creating an inconsistency where one constant is test-only and the other is always available.

Apply this diff to gate both constants consistently:

-#[cfg(all(test, target_family = "wasm"))]
-pub const WORKER_ERROR_TYPE_GENERIC: &str = "WorkerError";
-pub const WORKER_ERROR_TYPE_INITIALIZATION_PENDING: &str = "InitializationPending";
+#[cfg(all(test, target_family = "wasm"))]
+pub const WORKER_ERROR_TYPE_GENERIC: &str = "WorkerError";
+#[cfg(all(test, target_family = "wasm"))]
+pub const WORKER_ERROR_TYPE_INITIALIZATION_PENDING: &str = "InitializationPending";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[cfg(all(test, target_family = "wasm"))]
pub const WORKER_ERROR_TYPE_GENERIC: &str = "WorkerError";
pub const WORKER_ERROR_TYPE_INITIALIZATION_PENDING: &str = "InitializationPending";
#[cfg(all(test, target_family = "wasm"))]
pub const WORKER_ERROR_TYPE_GENERIC: &str = "WorkerError";
#[cfg(all(test, target_family = "wasm"))]
pub const WORKER_ERROR_TYPE_INITIALIZATION_PENDING: &str = "InitializationPending";
🤖 Prompt for AI Agents
In packages/sqlite-web/src/messages.rs around lines 1 to 3, the #[cfg(all(test,
target_family = "wasm"))] attribute currently only gates
WORKER_ERROR_TYPE_GENERIC (line 2) while
WORKER_ERROR_TYPE_INITIALIZATION_PENDING (line 3) is unconditionally compiled;
make the cfg scope consistent by applying the same #[cfg(all(test, target_family
= "wasm"))] attribute to the second constant as well (or wrap both constants in
a single module or block gated by that cfg) so both constants are compiled under
the same condition.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not an issue

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@findolor, understood! I see now that the different scoping is intentional—WORKER_ERROR_TYPE_GENERIC is test-only while WORKER_ERROR_TYPE_INITIALIZATION_PENDING is used in production code. Thank you for the clarification.


🧠 Learnings used
Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/messages.rs : Use structured message types for worker communication as defined in messages.rs

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/worker.rs : Keep worker.rs as the main worker entry point invoked by worker_main()

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/worker_template.rs : Ensure the worker JavaScript generated by worker_template.rs embeds the WASM (base64) and does not fetch external WASM files

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/lib.rs : Expose an async, promise-based query interface from the SQLiteWasmDatabase public API

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web/embedded_worker.js : Do not manually edit embedded_worker.js; it is generated by the build and should be treated as read-only

Learnt from: CR
Repo: rainlanguage/sqlite-web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T06:55:20.178Z
Learning: Applies to packages/sqlite-web-core/src/database_functions.rs : Integrate and expose rain.math.float-backed custom database functions for SQLite queries

Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 9
File: packages/sqlite-web-core/src/coordination.rs:52-65
Timestamp: 2025-09-15T06:11:31.781Z
Learning: In packages/sqlite-web-core/src/coordination.rs, the pattern of using `db.borrow_mut().take()` followed by async database operations and then putting the database back with `*db.borrow_mut() = Some(database)` is safe in their use case and doesn't cause concurrent access issues or "Database not initialized" errors.

Learnt from: findolor
Repo: rainlanguage/sqlite-web PR: 19
File: packages/sqlite-web-core/src/database.rs:122-157
Timestamp: 2025-10-20T12:24:07.874Z
Learning: In packages/sqlite-web-core/src/database.rs, named parameters (:name, name, $name) are intentionally not supported for SQL parameter binding. Only plain '?' and numbered '?N' placeholders are supported.

Comment on lines 334 to 335
is_leader: &Rc<RefCell<bool>>,
has_leader: &Rc<RefCell<bool>>,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it's best to avoid boolean blindness

https://medium.com/@itsme.mittal/boolean-blindness-60937910e40e

Comment on lines 382 to 383
ChannelMessage::LeaderPing { requester_id: _ } => {
if *is_leader.borrow() {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: would inlining the if not work?

Suggested change
ChannelMessage::LeaderPing { requester_id: _ } => {
if *is_leader.borrow() {
ChannelMessage::LeaderPing { requester_id: _ } if *is_leader.borrow() => {


let result = match JsFuture::from(promise).await {
Ok(value) => value,
Err(err) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can reduce nesting with if inlining here too

@findolor findolor requested a review from 0xgleb November 12, 2025 13:33
@findolor findolor merged commit 7aeaa48 into main Nov 17, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants