Skip to content

Commit 1899baf

Browse files
committed
test(driver): wait for wasm db sleep recovery
1 parent 4931c2e commit 1899baf

1 file changed

Lines changed: 49 additions & 32 deletions

File tree

rivetkit-typescript/packages/rivetkit/tests/driver/actor-db.test.ts

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @ts-nocheck
22

3-
import { describe, expect, test, vi } from "vitest";
3+
import { describe, expect, test } from "vitest";
44
import {
55
describeDriverMatrix,
66
SQLITE_DRIVER_MATRIX_OPTIONS,
@@ -13,6 +13,7 @@ const CHUNK_SIZE = 4096;
1313
const LARGE_PAYLOAD_SIZE = 32768;
1414
const HIGH_VOLUME_COUNT = 1000;
1515
const SLEEP_WAIT_MS = 150;
16+
const WASM_REMOTE_SLEEP_RECOVERY_TIMEOUT_MS = 30_000;
1617
const LIFECYCLE_POLL_INTERVAL_MS = 25;
1718
const LIFECYCLE_POLL_ATTEMPTS = 40;
1819
const REAL_TIMER_DB_TIMEOUT_MS = 180_000;
@@ -53,50 +54,50 @@ function isActorStoppingDbError(error: unknown): boolean {
5354
);
5455
}
5556

57+
async function retryActorStoppingDbError<T>(
58+
driverTestConfig: DriverTestConfig,
59+
fn: () => Promise<T>,
60+
timeoutMs: number,
61+
): Promise<T> {
62+
const deadline = Date.now() + timeoutMs;
63+
for (;;) {
64+
try {
65+
return await fn();
66+
} catch (error) {
67+
if (!isActorStoppingDbError(error) || Date.now() >= deadline) {
68+
throw error;
69+
}
70+
await waitFor(driverTestConfig, 100);
71+
}
72+
}
73+
}
74+
5675
async function runWithActorStoppingRetry(
57-
_driverTestConfig: DriverTestConfig,
76+
driverTestConfig: DriverTestConfig,
5877
fn: () => Promise<void>,
5978
): Promise<void> {
60-
// Wait for the actor to leave the `stopping` window. The driver does not
61-
// surface a "ready again" signal, so we poll the user function and only
62-
// retry on the specific `actor stopping: database accessed` error. Any
63-
// other failure short-circuits.
64-
await vi.waitFor(
65-
async () => {
66-
try {
67-
await fn();
68-
} catch (error) {
69-
if (isActorStoppingDbError(error)) {
70-
throw error;
71-
}
72-
throw new (class extends Error {
73-
override name = "AbortRetry";
74-
})(error instanceof Error ? error.message : String(error));
75-
}
76-
},
77-
{ timeout: SLEEP_WAIT_MS * 4, interval: 100 },
79+
await retryActorStoppingDbError(
80+
driverTestConfig,
81+
fn,
82+
SLEEP_WAIT_MS * 4,
7883
);
7984
}
8085

8186
async function expectIntegrityCheckOk(
82-
_driverTestConfig: DriverTestConfig,
87+
driverTestConfig: DriverTestConfig,
8388
integrityCheck: () => Promise<string>,
8489
): Promise<void> {
8590
// Same lifecycle window as `runWithActorStoppingRetry`: the integrity
8691
// check is read-only against the SQLite db, so polling it does not hold
8792
// the actor awake.
88-
await vi.waitFor(
93+
await retryActorStoppingDbError(
94+
driverTestConfig,
8995
async () => {
90-
try {
91-
expect((await integrityCheck()).toLowerCase()).toBe("ok");
92-
} catch (error) {
93-
if (isActorStoppingDbError(error)) {
94-
throw error;
95-
}
96-
throw error;
97-
}
96+
expect((await integrityCheck()).toLowerCase()).toBe("ok");
9897
},
99-
{ timeout: SLEEP_WAIT_MS * 8, interval: 100 },
98+
driverTestConfig.runtime === "wasm"
99+
? WASM_REMOTE_SLEEP_RECOVERY_TIMEOUT_MS
100+
: SLEEP_WAIT_MS * 8,
100101
);
101102
}
102103

@@ -276,6 +277,7 @@ describeDriverMatrix("Actor Db", (driverTestConfig) => {
276277
expect(
277278
sleepEvent.timestamp - sleepRequestedAt,
278279
).toBeLessThanOrEqual(SLEEP_OBSERVER_TIMEOUT_MS);
280+
await waitFor(driverTestConfig, SLEEP_WAIT_MS);
279281

280282
const countAfterWake = await actor.getCount();
281283
expect(countAfterWake).toBe(baselineCount);
@@ -508,11 +510,18 @@ describeDriverMatrix("Actor Db", (driverTestConfig) => {
508510
c,
509511
driverTestConfig,
510512
);
513+
const actorKey = `db-${variant}-integrity-${crypto.randomUUID()}`;
514+
const observerKey = `${actorKey}-observer`;
515+
const observer = client.lifecycleObserver.getOrCreate([
516+
observerKey,
517+
]);
518+
await observer.clearEvents();
511519
const actor = getDbActor(client, variant).getOrCreate([
512-
`db-${variant}-integrity-${crypto.randomUUID()}`,
520+
actorKey,
513521
]);
514522

515523
await actor.reset();
524+
await actor.configureLifecycleObserver(observerKey);
516525
await runWithActorStoppingRetry(
517526
driverTestConfig,
518527
async () =>
@@ -526,7 +535,15 @@ describeDriverMatrix("Actor Db", (driverTestConfig) => {
526535
async () => await actor.integrityCheck(),
527536
);
528537

538+
const sleepRequestedAt = Date.now();
529539
await actor.triggerSleep();
540+
await waitForDbLifecycleEvent(
541+
driverTestConfig,
542+
observer,
543+
actorKey,
544+
"sleep",
545+
sleepRequestedAt,
546+
);
530547
await expectIntegrityCheckOk(
531548
driverTestConfig,
532549
async () => await actor.integrityCheck(),

0 commit comments

Comments
 (0)