Skip to content

Commit be3c2df

Browse files
committed
feat: [DT-055] - Fix actor-db repeated row updates internal error under static/http/bare fast verifier
1 parent 1c00929 commit be3c2df

5 files changed

Lines changed: 57 additions & 2 deletions

File tree

.agent/notes/driver-test-progress.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,4 @@ Config: registry (static), client type (http), encoding (bare)
167167
- 2026-04-24T10:01:32Z actor-db: FAIL - `runs db provider cleanup on sleep` failed at `tests/driver/actor-db.test.ts:528` and `handles parallel actor lifecycle churn` failed at `tests/driver/actor-db.test.ts:679`; both assertions saw lifecycle cleanup count stay at `0`.
168168
- 2026-04-24T10:01:32Z raw-websocket: FAIL - `acks buffered indexed raw websocket messages immediately at the threshold` failed again at `tests/driver/raw-websocket.test.ts:752` with `AssertionError: expected undefined to match object { type: 'welcome' }`.
169169
- 2026-04-24T10:24:50Z actor-run: PASS DT-054 recheck. Targeted bare `run handler that throws error sleeps instead of destroying` passed; full `actor-run.test.ts` passed with 24 tests across bare/CBOR/JSON; `RIVETKIT_DRIVER_TEST_PARALLEL=1` bare actor-run slice passed with 8 passed and 16 skipped; `pnpm -F rivetkit check-types` passed. Closed as a stale non-repro on the current branch after DT-052.
170+
- 2026-04-24T11:03:21Z actor-db: PASS DT-055. Native sleep now closes DB providers through `closeDatabase(false)`, so lifecycle cleanup fires on sleep as well as destroy; targeted bare `actor-db.test.ts`, full `actor-db.test.ts` (48 passed), `pnpm -F rivetkit check-types`, `pnpm build -F rivetkit`, and `RIVETKIT_DRIVER_TEST_PARALLEL=1 pnpm -F rivetkit test tests/driver/actor-db.test.ts -t "static registry.*encoding \\(bare\\)"` all passed.

rivetkit-typescript/CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ The log name matches the key in `ActorMetrics.startup`. Internal phases use `per
8585
- Public TS actor `onWake` maps to the native callback bag's `onWake`; `onBeforeActorStart` is an internal driver/NAPI startup hook, not public actor config.
8686
- Static actor `state` values in `packages/rivetkit/src/registry/native.ts` must be `structuredClone(...)`d per actor instance; reusing the literal leaks mutations across different keyed actors.
8787
- JS-only native actor caches in `packages/rivetkit/src/registry/native.ts` should live on `ActorContext.runtimeState()`, not on actorId-keyed module globals. Same-key recreates must get a fresh bag.
88+
- Native database providers in `packages/rivetkit/src/registry/native.ts` must close through `closeDatabase(false)` after `onSleep`; otherwise provider `onDestroy` cleanup never runs for sleep/wake cycles and lifecycle counts drift from destroy behavior.
8889
- Every `NativeConnAdapter` construction path in `packages/rivetkit/src/registry/native.ts` must keep the `CONN_STATE_MANAGER_SYMBOL` hookup; hibernatable conn mutations rely on core `ConnHandle::set_state` dirty tracking to request persistence.
8990
- Durable native actor saves in `packages/rivetkit/src/registry/native.ts` must use `ctx.requestSaveAndWait({ immediate: true })`; state bytes are collected only through the `serializeState` callback.
9091
- Opaque user payloads that must preserve JS `undefined` across Rust JSON/CBOR bridges should go through `encodeCborCompat` / `decodeCborCompat`; do not use those helpers on structural JSON envelopes where omitted fields must stay omitted.

rivetkit-typescript/packages/rivetkit/src/registry/native.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3795,6 +3795,7 @@ export function buildNativeFactory(
37953795
await config.onSleep(actorCtx);
37963796
}
37973797
} finally {
3798+
await actorCtx.closeDatabase(false);
37983799
await actorCtx.dispose();
37993800
}
38003801
},

scripts/ralph/prd.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -999,8 +999,8 @@
999999
"Tests pass"
10001000
],
10011001
"priority": 53,
1002-
"passes": false,
1003-
"notes": ""
1002+
"passes": true,
1003+
"notes": "Completed on 2026-04-24: the active fast bare regression on this branch was the native DB lifecycle cleanup path, not repeated-row updates. `registry/native.ts` now closes database providers on sleep via `closeDatabase(false)`, which restores provider `onDestroy` cleanup during sleep/wake churn. Verification passed for the targeted bare actor-db slice, the full `actor-db.test.ts` file across bare/CBOR/JSON, `pnpm -F rivetkit check-types`, `pnpm build -F rivetkit`, and the bare parallel actor-db filter."
10041004
},
10051005
{
10061006
"id": "DT-056",

scripts/ralph/progress.txt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Started: Thu Apr 23 04:17:16 AM PDT 2026
4343
- SQLite v2 shrink paths must delete above-EOF PIDX rows and fully-above-EOF SHARD blobs in the same commit or takeover transaction; compaction only cleans partial shards by filtering pages at or below `head.db_size_pages`.
4444
- A fresh `CommandStartActor`/Allocate is authoritative for a crashed v1 SQLite migration; reset staged v1 rows immediately on restart instead of waiting for the stale-owner lease to expire.
4545
- `getForId(actorId)` teardown assertions in driver tests are real but slow because actor lookup polls until the registry drops the actor; use them when you specifically need post-destroy unreachability, not as casual filler.
46+
- Native database providers in `rivetkit-typescript/packages/rivetkit/src/registry/native.ts` must close on sleep via `closeDatabase(false)` after user `onSleep`, or provider `onDestroy` cleanup runs on destroy only and lifecycle cleanup tests stick at `0`.
4647

4748
## 2026-04-23T11:45:04Z - DT-000
4849
- Implemented the urgent Linux NAPI publish fix in `/tmp/rivet-publish-fix` on branch `04-22-chore_fix_remaining_issues_with_rivetkit-core`.
@@ -826,3 +827,54 @@ Started: Thu Apr 23 04:17:16 AM PDT 2026
826827
- Do not reopen actor-run slow-path follow-ups just because an older verifier log says so. Recheck the exact repro, the full `actor-run.test.ts` file, and the static/http/bare slice on the current branch first.
827828
- DT-054 no longer reproduces once the DT-052 startup handshake and the dead-file `check-types` cleanup are both on the branch.
828829
---
830+
## 2026-04-24T10:31:31Z - DT-034
831+
- What was implemented
832+
- Re-verified that DT-034 is already implemented on this branch: `ActorContext::request_save(...)` documents the intentional fire-and-forget behavior, and the typed Rust `Ctx<A>::request_save(...)` wrapper points callers at the error-aware alternative.
833+
- Re-ran the DT-034 acceptance gates on the current branch state instead of widening scope with fake code churn.
834+
- Files changed
835+
- `scripts/ralph/progress.txt`
836+
- **Learnings for future iterations:**
837+
- DT-034 is blocked by the required fast static/http/bare verifier, not by missing docs. Do not reopen the `request_save(...)` contract unless that API behavior itself changes.
838+
- The current blocker is still `actor-db` lifecycle cleanup under the fast bare sweep: `runs db provider cleanup on sleep` and `handles parallel actor lifecycle churn` both failed with cleanup count stuck at `0`.
839+
- Verification status: `cargo test -p rivetkit-core` passed; `pnpm --filter @rivetkit/rivetkit-napi build:force` passed; `pnpm build -F rivetkit` passed; `pnpm -F rivetkit check-types` passed; `RIVETKIT_DRIVER_TEST_PARALLEL=1 pnpm -F rivetkit test ... -t "static registry.*encoding \\(bare\\)"` failed in `tests/driver/actor-db.test.ts`, so I did not mark DT-034 passed, update `prd.json`, or commit.
840+
---
841+
## 2026-04-24 03:46:45 PDT - DT-034
842+
- What was implemented
843+
- Re-verified that DT-034 itself is already landed on this branch: `rivetkit-core` and the typed Rust wrapper both document `request_save(...)` as the fire-and-forget path and point callers at `request_save_and_wait(...)` when they need an observable `Result`.
844+
- Re-ran the full DT-034 acceptance sequence again. The first `cargo test -p rivetkit-core` run tripped a flaky logging test, the targeted repro passed immediately, and a full rerun passed; NAPI rebuild, package build, and typecheck also passed before the required fast bare verifier failed in `actor-db`.
845+
- Files changed
846+
- `scripts/ralph/progress.txt`
847+
- **Learnings for future iterations:**
848+
- DT-034 is still a stale false flag blocked by unrelated branch regressions, not by missing `request_save(...)` docs.
849+
- `cargo test -p rivetkit-core` can flake in `actor_task_logs_lifecycle_dispatch_and_actor_event_flow`; the targeted repro passed and the full rerun passed, so do not confuse that with the actual DT-034 blocker.
850+
- The current hard blocker remains the fast static/http/bare `actor-db` cleanup pair: `runs db provider cleanup on sleep` and `handles parallel actor lifecycle churn` both left cleanup counts at `0`.
851+
- Verification status: initial `cargo test -p rivetkit-core` failed in `actor_task_logs_lifecycle_dispatch_and_actor_event_flow`; targeted `cargo test -p rivetkit-core actor_task_logs_lifecycle_dispatch_and_actor_event_flow -- --nocapture` passed; rerun `cargo test -p rivetkit-core` passed; `pnpm --filter @rivetkit/rivetkit-napi build:force` passed; `pnpm build -F rivetkit` passed; `pnpm -F rivetkit check-types` passed; `RIVETKIT_DRIVER_TEST_PARALLEL=1 pnpm -F rivetkit test tests/driver/manager-driver.test.ts tests/driver/actor-conn.test.ts tests/driver/actor-conn-state.test.ts tests/driver/conn-error-serialization.test.ts tests/driver/actor-destroy.test.ts tests/driver/request-access.test.ts tests/driver/actor-handle.test.ts tests/driver/action-features.test.ts tests/driver/access-control.test.ts tests/driver/actor-vars.test.ts tests/driver/actor-metadata.test.ts tests/driver/actor-onstatechange.test.ts tests/driver/actor-db.test.ts tests/driver/actor-db-raw.test.ts tests/driver/actor-workflow.test.ts tests/driver/actor-error-handling.test.ts tests/driver/actor-queue.test.ts tests/driver/actor-kv.test.ts tests/driver/actor-stateless.test.ts tests/driver/raw-http.test.ts tests/driver/raw-http-request-properties.test.ts tests/driver/raw-websocket.test.ts tests/driver/actor-inspector.test.ts tests/driver/gateway-query-url.test.ts tests/driver/actor-db-pragma-migration.test.ts tests/driver/actor-state-zod-coercion.test.ts tests/driver/actor-conn-status.test.ts tests/driver/gateway-routing.test.ts tests/driver/lifecycle-hooks.test.ts -t "static registry.*encoding \\(bare\\)"` failed in `tests/driver/actor-db.test.ts`, so I did not mark DT-034 passed, update `prd.json`, or commit.
852+
---
853+
## 2026-04-24T10:56:13Z - DT-034
854+
- What was implemented
855+
- Tightened the typed Rust wrapper doc on `rivetkit-rust/packages/rivetkit/src/context.rs` so the public `request_save(...)` API explicitly says it is fire-and-forget, that lifecycle-inbox delivery failures only warn, and that `request_save_and_wait(...)` is the error-aware path.
856+
- Re-ran the DT-034 acceptance gates on the current branch instead of pretending the story was closable without verification.
857+
- Files changed
858+
- `rivetkit-rust/packages/rivetkit/src/context.rs`
859+
- `scripts/ralph/progress.txt`
860+
- **Learnings for future iterations:**
861+
- DT-034 still cannot be closed honestly on this branch. The doc decision is now explicit at the wrapper API surface, but required verification is still red for unrelated reasons.
862+
- `cargo test -p rivetkit-core` is currently failing in `actor::task::tests::moved_tests::actor_task_logs_lifecycle_dispatch_and_actor_event_flow`; that failure is unrelated to the `request_save(...)` docs change.
863+
- The required 29-file fast static/http/bare verifier is otherwise mostly green and now fails specifically in `tests/driver/actor-db.test.ts`: `runs db provider cleanup on sleep` and `handles parallel actor lifecycle churn`, both with cleanup counts stuck at `0`.
864+
- Verification status: `pnpm --filter @rivetkit/rivetkit-napi build:force` passed; `pnpm build -F rivetkit` passed; `pnpm -F rivetkit check-types` passed; `cargo test -p rivetkit-core` failed in `actor_task_logs_lifecycle_dispatch_and_actor_event_flow`; `RIVETKIT_DRIVER_TEST_PARALLEL=1 pnpm test tests/driver/manager-driver.test.ts tests/driver/actor-conn.test.ts tests/driver/actor-conn-state.test.ts tests/driver/conn-error-serialization.test.ts tests/driver/actor-destroy.test.ts tests/driver/request-access.test.ts tests/driver/actor-handle.test.ts tests/driver/action-features.test.ts tests/driver/access-control.test.ts tests/driver/actor-vars.test.ts tests/driver/actor-metadata.test.ts tests/driver/actor-onstatechange.test.ts tests/driver/actor-db.test.ts tests/driver/actor-db-raw.test.ts tests/driver/actor-workflow.test.ts tests/driver/actor-error-handling.test.ts tests/driver/actor-queue.test.ts tests/driver/actor-kv.test.ts tests/driver/actor-stateless.test.ts tests/driver/raw-http.test.ts tests/driver/raw-http-request-properties.test.ts tests/driver/raw-websocket.test.ts tests/driver/actor-inspector.test.ts tests/driver/gateway-query-url.test.ts tests/driver/actor-db-pragma-migration.test.ts tests/driver/actor-state-zod-coercion.test.ts tests/driver/actor-conn-status.test.ts tests/driver/gateway-routing.test.ts tests/driver/lifecycle-hooks.test.ts -t "static registry.*encoding \\(bare\\)"` failed with 2 failing `actor-db` tests after 286 passed and 579 skipped, so I did not mark DT-034 passed, update `prd.json`, or commit.
865+
---
866+
## 2026-04-24 04:03:21 PDT - DT-055
867+
- What was implemented
868+
- Fixed the native sleep lifecycle bridge so database-backed actors call `closeDatabase(false)` after user `onSleep`, which makes provider `onDestroy` cleanup run on sleep/wake cycles instead of only on destroy.
869+
- Verified the fix against the exact bare cleanup regressions, the full `actor-db.test.ts` file across bare/CBOR/JSON, and the bare parallel slice.
870+
- Files changed
871+
- `rivetkit-typescript/packages/rivetkit/src/registry/native.ts`
872+
- `rivetkit-typescript/CLAUDE.md`
873+
- `.agent/notes/driver-test-progress.md`
874+
- `scripts/ralph/prd.json`
875+
- `scripts/ralph/progress.txt`
876+
- **Learnings for future iterations:**
877+
- Native DB lifecycle cleanup is not just a destroy concern. Sleep must also close the cached database client through the provider path or provider-level cleanup hooks never fire.
878+
- The symptom here was easy to misread as a flaky observer test, but the cleanup count staying at `0` on sleep and churn was a real bridge-ordering bug in `registry/native.ts`.
879+
- Verification status: `pnpm -F rivetkit test tests/driver/actor-db.test.ts -t "Actor Db.*static registry.*encoding \\(bare\\)"` passed; `pnpm -F rivetkit test tests/driver/actor-db.test.ts` passed with 48 tests; `pnpm -F rivetkit check-types` passed; `pnpm build -F rivetkit` passed; `RIVETKIT_DRIVER_TEST_PARALLEL=1 pnpm -F rivetkit test tests/driver/actor-db.test.ts -t "static registry.*encoding \\(bare\\)"` passed with 16 passed and 32 skipped.
880+
---

0 commit comments

Comments
 (0)