Skip to content

record-adapter-do-sqlite — a Workers story that fits the sync SqlExecutor and the ownership rule #161

Description

@cuibonobo

Problem

With record-adapter-sqljs removed, there is no adapter for non-Node runtimes. sql.js was meant to serve that case and could not: Workers forbid compiling WASM from bytes at runtime, and its whole-database-serialize-per-write persist model has no single-writer guarantee, so a Worker fleet would silently lose writes.

Cloudflare Durable Objects with SQLite storage is the shape that actually fits — and it fits this codebase specifically, not just the runtime:

  • ctx.storage.sql.exec() is synchronous. SqlExecutor (packages/sqlite-shared/src/executor.ts) is a synchronous interface and all of SharedSqlRecordLogic is built on it. A DO adapter drops onto it as-is. D1 and libsql-over-HTTP are both async and would force an async refactor of the entire shared layer — that cost is the reason to prefer this over either.
  • DO supports FTS5, the same module record-adapter-sqlite uses, so this rejoins the shared FTS path with no pluggable seam.
  • A DO instance is a single owning writer. docs/spec/adapters.md § Concurrency & storage ownership requires exactly one owning process per stack's storage; a Durable Object implements that constraint rather than delegating it to the host.

Work items

  • record-adapter-do-sqliteStackRecordAdapter with a SqlExecutor over ctx.storage.sql, reusing SharedSqlRecordLogic, the FTS5 schema and strategy, the query builder, cursor codec, and row mappers
  • Engine-specific surface only: construction from the DO's ctx, SqlStorageCursor → row-object normalization, lifecycle (no lock file — the DO is the lock; no persist callback — storage is durable by construction)
  • Confirm the error-message probes in sqlite-shared/src/executor.ts (isForeignKeyViolation, isUniqueConstraintViolation) match what DO's SQLite build reports; they currently pin exact strings that happen to agree across sql.js and node:sqlite
  • Spec: a bullet in docs/spec/adapters.md § Concurrency & storage ownership for how this adapter honors single-writer
  • Tests against the Workers runtime (@cloudflare/vitest-pool-workers) rather than under environment: 'node' — the sql.js package's tests only ever exercised Node, which is how a browser/Worker adapter shipped without ever running in a browser or a Worker

Notes

Not urgent, and worth confirming there's real demand before building it — it's listed as the answer if a Workers story is wanted, not a commitment to one. Explicitly not libsql: @libsql/client on Workers is a remote HTTP client to Turso, which is closer in kind to adapter-api than to an embedded storage adapter, and is async.

Cross-refs: #93 (optional-capability discovery). Blob storage in this topology would be R2 via #160.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions