From f676d130a06529c31be6b93ad242c02c6a1ad0b3 Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Tue, 14 Apr 2026 19:07:56 -0700 Subject: [PATCH] test(rivetkit): stabilize actor db driver tests --- .../src/driver-test-suite/tests/actor-db.ts | 80 ++++++++++++++++--- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/rivetkit-typescript/packages/rivetkit/src/driver-test-suite/tests/actor-db.ts b/rivetkit-typescript/packages/rivetkit/src/driver-test-suite/tests/actor-db.ts index 9e907015f5..1fc39c1b85 100644 --- a/rivetkit-typescript/packages/rivetkit/src/driver-test-suite/tests/actor-db.ts +++ b/rivetkit-typescript/packages/rivetkit/src/driver-test-suite/tests/actor-db.ts @@ -44,6 +44,54 @@ function isActorStoppingDbError(error: unknown): boolean { ); } +async function runWithActorStoppingRetry( + driverTestConfig: DriverTestConfig, + fn: () => Promise, +): Promise { + let lastError: unknown; + + for (let attempt = 0; attempt < 3; attempt += 1) { + try { + await fn(); + return; + } catch (error) { + if (!isActorStoppingDbError(error)) { + throw error; + } + + lastError = error; + } + + await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100); + } + + throw lastError; +} + +async function expectIntegrityCheckOk( + driverTestConfig: DriverTestConfig, + integrityCheck: () => Promise, +): Promise { + let lastError: unknown; + + for (let attempt = 0; attempt < 6; attempt += 1) { + try { + expect((await integrityCheck()).toLowerCase()).toBe("ok"); + return; + } catch (error) { + if (!isActorStoppingDbError(error)) { + throw error; + } + + lastError = error; + } + + await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100); + } + + throw lastError; +} + function getDbActor( client: Awaited>["client"], variant: DbVariant, @@ -61,7 +109,7 @@ export function runActorDbTests(driverTestConfig: DriverTestConfig) { : undefined; for (const variant of variants) { - describe(`Actor Database (${variant}) Tests`, () => { + describe.sequential(`Actor Database (${variant}) Tests`, () => { test( "bootstraps schema on startup", async (c) => { @@ -468,17 +516,23 @@ export function runActorDbTests(driverTestConfig: DriverTestConfig) { ]); await actor.reset(); - await actor.runMixedWorkload( - INTEGRITY_SEED_COUNT, - INTEGRITY_CHURN_COUNT, + await runWithActorStoppingRetry( + driverTestConfig, + async () => + await actor.runMixedWorkload( + INTEGRITY_SEED_COUNT, + INTEGRITY_CHURN_COUNT, + ), ); - expect((await actor.integrityCheck()).toLowerCase()).toBe( - "ok", + await expectIntegrityCheckOk( + driverTestConfig, + async () => await actor.integrityCheck(), ); await actor.triggerSleep(); - expect((await actor.integrityCheck()).toLowerCase()).toBe( - "ok", + await expectIntegrityCheckOk( + driverTestConfig, + async () => await actor.integrityCheck(), ); }, dbTestTimeout, @@ -486,7 +540,12 @@ export function runActorDbTests(driverTestConfig: DriverTestConfig) { }); } - describe("Actor Database Lifecycle Cleanup Tests", () => { + // These assertions rely on the fixture's module-global lifecycle counters. + // Dynamic actors and the observer actor run in separate isolates, so those + // globals are not shared across actors there. + describe.skipIf(driverTestConfig.isDynamic)( + "Actor Database Lifecycle Cleanup Tests", + () => { test( "runs db provider cleanup on sleep", async (c) => { @@ -674,5 +733,6 @@ export function runActorDbTests(driverTestConfig: DriverTestConfig) { }, lifecycleTestTimeout, ); - }); + }, + ); }