Skip to content

Commit fb54be9

Browse files
committed
feat: sqlite v2
1 parent 878ade3 commit fb54be9

130 files changed

Lines changed: 27250 additions & 840 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agent/research/sqlite/sqlite-vfs-ltx-redesign.md

Lines changed: 530 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"capturedAt": "2026-04-16T03:05:23.184Z",
3+
"vfsVersion": "v1",
4+
"source": "examples/sqlite-raw/scripts/benchmark.ts",
5+
"pageSizeBytes": 4096,
6+
"environment": {
7+
"benchmarkHarness": "examples/sqlite-raw wrapper over rivetkit-sqlite-native/examples/v1_baseline_bench.rs",
8+
"rttMs": 0,
9+
"storage": "in-memory SqliteKv benchmark driver exercising the v1 native VFS",
10+
"platform": "linux",
11+
"release": "6.1.0-41-amd64",
12+
"arch": "x64",
13+
"cpuModel": "12th Gen Intel(R) Core(TM) i7-12700KF",
14+
"cpuCount": 20,
15+
"totalMemoryGiB": 62.56
16+
},
17+
"workloads": [
18+
{
19+
"name": "1 MiB insert",
20+
"latencyMs": 3.614,
21+
"roundTrips": 298
22+
},
23+
{
24+
"name": "10 MiB insert",
25+
"latencyMs": 25.892,
26+
"roundTrips": 2606
27+
},
28+
{
29+
"name": "hot-row update",
30+
"latencyMs": 1.036,
31+
"roundTrips": 109
32+
},
33+
{
34+
"name": "cold read",
35+
"latencyMs": 1.729,
36+
"roundTrips": 228
37+
},
38+
{
39+
"name": "mixed read/write",
40+
"latencyMs": 0.824,
41+
"roundTrips": 62
42+
}
43+
]
44+
}

.claude/scheduled_tasks.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"sessionId":"cb4dbb44-01ef-4eef-91a8-ff5ad2f3e6fe","pid":1948414,"acquiredAt":1776308226245}

CLAUDE.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,16 @@ When the user asks to track something in a note, store it in `.agent/notes/` by
213213

214214
## Architecture
215215

216+
### Deprecated Packages
217+
- `engine/packages/pegboard-runner/` and associated TypeScript "runner" packages (`engine/sdks/typescript/runner`, `rivetkit-typescript/packages/engine-runner/`) and runner workflows are deprecated. All new actor hosting work targets `engine/packages/pegboard-envoy/` exclusively. Do not add features to or fix bugs in the deprecated runner path.
218+
216219
### Monorepo Structure
217220
- This is a Rust workspace-based monorepo for Rivet with the following key packages and components:
218221

219222
- **Core Engine** (`packages/core/engine/`) - Main orchestration service that coordinates all operations
220223
- **Workflow Engine** (`packages/common/gasoline/`) - Handles complex multi-step operations with reliability and observability
221224
- **Pegboard** (`packages/core/pegboard/`) - Actor/server lifecycle management system
225+
- **Pegboard Envoy** (`engine/packages/pegboard-envoy/`) - The active actor-to-engine bridge. All new actor hosting work goes here.
222226
- **Common Packages** (`/packages/common/`) - Foundation utilities, database connections, caching, metrics, logging, health checks, workflow engine core
223227
- **Core Packages** (`/packages/core/`) - Main engine executable, Pegboard actor orchestration, workflow workers
224228
- **Shared Libraries** (`shared/{language}/{package}/`) - Libraries shared between the engine and rivetkit (e.g., `shared/typescript/virtual-websocket/`)
@@ -290,6 +294,12 @@ let error_with_meta = ApiRateLimited { limit: 100, reset_at: 1234567890 }.build(
290294
**Native SQLite & KV Channel**
291295
- RivetKit SQLite is served by `@rivetkit/rivetkit-native`. Do not reintroduce SQLite-over-KV or WebAssembly SQLite paths in the TypeScript runtime.
292296
- The Rust KV-backed SQLite implementation still lives in `rivetkit-typescript/packages/sqlite-native/src/`. When changing its on-disk or KV layout, update the internal data-channel spec in the same change.
297+
- SQLite v2 slow-path staging writes encoded LTX bytes directly under DELTA chunk keys. Do not expect `/STAGE` keys or a fixed one-chunk-per-page mapping in tests or recovery code.
298+
- The native VFS uses the same 4 KiB chunk layout and KV key encoding as the WASM VFS. Data is compatible between backends.
299+
- **The native Rust VFS and the WASM TypeScript VFS must match 1:1.** This includes: KV key layout and encoding, chunk size, PRAGMA settings, VFS callback-to-KV-operation mapping, delete/truncate strategy (both must use `deleteRange`), and journal mode. When changing any VFS behavior in one implementation, update the other. The relevant files are:
300+
- Native: `rivetkit-typescript/packages/sqlite-native/src/vfs.rs`, `kv.rs`
301+
- WASM: `rivetkit-typescript/packages/sqlite-wasm/src/vfs.ts`, `kv.ts`
302+
- SQLite VFS v2 storage keys use literal ASCII path segments under the `0x02` subspace prefix with big-endian numeric suffixes so `scan_prefix` and `BTreeMap` ordering stay numerically correct.
293303
- Full spec: `docs-internal/engine/NATIVE_SQLITE_DATA_CHANNEL.md`
294304

295305
**Inspector HTTP API**

Cargo.lock

Lines changed: 37 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ members = [
3838
"engine/packages/runner-protocol",
3939
"engine/packages/runtime",
4040
"engine/packages/service-manager",
41+
"engine/packages/sqlite-storage",
4142
"engine/packages/telemetry",
4243
"engine/packages/test-deps",
4344
"engine/packages/test-deps-docker",
@@ -108,6 +109,7 @@ members = [
108109
once_cell = "1.20.2"
109110
opentelemetry-appender-tracing = "0.28.1"
110111
papaya = "0.2.1"
112+
parking_lot = "0.12"
111113
pest_derive = "2.7"
112114
portpicker = "0.1"
113115
prettyplease = "0.2"
@@ -460,6 +462,9 @@ members = [
460462
[workspace.dependencies.rivet-runtime]
461463
path = "engine/packages/runtime"
462464

465+
[workspace.dependencies.sqlite-storage]
466+
path = "engine/packages/sqlite-storage"
467+
463468
[workspace.dependencies.rivet-service-manager]
464469
path = "engine/packages/service-manager"
465470

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# SQLite Metrics
2+
3+
- `sqlite_commit_phase_duration_seconds{phase,path}`: Engine-side histogram for commit request phases. `path` is `fast` or `slow`. `phase` is `decode_request`, `meta_read`, `ltx_encode`, `pidx_read`, `udb_write`, or `response_build`.
4+
- `sqlite_commit_stage_phase_duration_seconds{phase}`: Engine-side histogram for staged commit uploads. `phase` is `decode`, `stage_encode`, or `udb_write`.
5+
- `sqlite_commit_finalize_phase_duration_seconds{phase}`: Engine-side histogram for staged commit finalize work. `phase` is `stage_promote`, `pidx_write`, or `meta_write`.
6+
- `sqlite_commit_dirty_page_count{path}`: Histogram of dirty page counts per commit path.
7+
- `sqlite_commit_dirty_bytes{path}`: Histogram of raw dirty-page bytes per commit path.
8+
- `sqlite_udb_ops_per_commit{path}`: Histogram of UniversalDB operations per commit path.
9+
- `sqlite_commit_envoy_dispatch_duration_seconds`: Pegboard-envoy histogram for websocket frame arrival to `sqlite-storage` dispatch.
10+
- `sqlite_commit_envoy_response_duration_seconds`: Pegboard-envoy histogram for `sqlite-storage` return to websocket response send.
11+
- `sqlite_commit_phases`: Actor inspector labeled timing metric exposed from `/inspector/metrics`. Values are `request_build`, `serialize`, `transport`, and `state_update`.
12+
13+
## Scrape Points
14+
15+
- Engine and pegboard-envoy Prometheus metrics come from the shared `/metrics` endpoint on port `6430`.
16+
- Actor-local commit timings come from `GET /inspector/metrics` on the actor gateway route.
17+
18+
## Tracing
19+
20+
- Set `RUST_LOG=sqlite_storage=debug,pegboard_envoy=debug,sqlite_v2_vfs=debug` to emit per-commit phase spans and VFS phase logs.
21+
- `sqlite-storage` commit handlers use debug spans for the high-level request and sub-phase work.
22+
- The VFS logs request-build, serialize, transport, and state-update timings after each successful commit.
23+
24+
## Diagnosis
25+
26+
- High `decode_request` or `sqlite_commit_envoy_dispatch_duration_seconds` usually means envoy-side validation or actor lookup is slow before storage work starts.
27+
- High `meta_read` or `pidx_read` points at UniversalDB read pressure or cache misses.
28+
- High `ltx_encode` means commit encoding and compression are doing real work. Check dirty page counts and raw dirty bytes together.
29+
- High `udb_write`, `meta_write`, or `sqlite_commit_envoy_response_duration_seconds` points at write-path latency after encode.
30+
- A healthy actor should show non-zero `sqlite_commit_phases` totals after commits in `/inspector/metrics`. If SQL runs but those timings stay zero, the native VFS metrics path is broken.

0 commit comments

Comments
 (0)