diff --git a/doc/idle-approval-queue-seeding.md b/doc/idle-approval-queue-seeding.md index 7f7e967d837..8e788fdc03a 100644 --- a/doc/idle-approval-queue-seeding.md +++ b/doc/idle-approval-queue-seeding.md @@ -136,3 +136,10 @@ route suite separately exposed cold imports inside timed tests. Moving those imports to suite loading preserves assertions and prevents timed-out requests from leaking into later mock state. The watchdog fixture collision from CI uses monotonic identifiers instead; its 19 real-PostgreSQL cases pass. + +The next CI run passed the security gate and the two originally failing shards. +Its remaining server shard caught a historical cleanup test checking 33 provider +inspections after only 32 had completed. The test advanced fake time before the +previous asynchronous page had necessarily published its next deadline. It now +waits for all 33 inspections, then retains the zero-further-work assertions. All +14 environment cleanup cases pass on real PostgreSQL; production code is unchanged. diff --git a/server/src/__tests__/environment-cleanup-work.test.ts b/server/src/__tests__/environment-cleanup-work.test.ts index 7f6b1d64c12..a730d8b2e42 100644 --- a/server/src/__tests__/environment-cleanup-work.test.ts +++ b/server/src/__tests__/environment-cleanup-work.test.ts @@ -17,17 +17,20 @@ import { historicalCleanupVerificationService } from "../services/historical-cle import { heartbeatService } from "../services/heartbeat.js"; import { environmentRuntimeService } from "../services/environment-runtime.js"; -const support = await getEmbeddedPostgresTestSupport(); +import { resolveExternalTestDatabaseUrl } from "./helpers/external-test-database.js"; + +const external = resolveExternalTestDatabaseUrl("PAPERCLIP_ENVIRONMENT_CLEANUP_TEST_DATABASE_URL"); +const support = external ? { supported: true } : await getEmbeddedPostgresTestSupport(); describe.skipIf(!support.supported)("environment cleanup scheduling", () => { - let database: Awaited>, db: ReturnType; + let database: Awaited> | undefined, db: ReturnType; let companyId: string, environmentId: string, draining: boolean, failing: boolean; let coordinator: ReturnType | undefined; let worker: ReturnType | undefined; let releases: ReturnType, inspections: ReturnType, reads: ReturnType; const errors: unknown[] = [], disposers: Array<() => void> = []; beforeAll(async () => { - database = await startEmbeddedPostgresTestDatabase("environment-cleanup-work-"); - db = createDb(database.connectionString, { maxConnections: 6, idleTimeoutSeconds: 0, maxLifetimeSeconds: 0 }); + if (!external) database = await startEmbeddedPostgresTestDatabase("environment-cleanup-work-"); + db = createDb(external ?? database!.connectionString, { maxConnections: 6, idleTimeoutSeconds: 0, maxLifetimeSeconds: 0 }); await Promise.all(Array.from({ length: 6 }, () => db.execute(sql`select pg_sleep(0.01)`))); }, 90_000); beforeEach(async () => { @@ -225,7 +228,12 @@ describe.skipIf(!support.supported)("environment cleanup scheduling", () => { for (let i = 0; i < 33; i++) { const lease = await pending(); await environmentService(db).releaseLease(lease.id, "failed", { cleanupStatus: "success" }); } - await start(true); await settle(300_000); await settle(300_000); expect(inspections).toHaveBeenCalledTimes(33); await quiet(); + await start(true); + await vi.waitFor(async () => { + await settle(300_000); + expect(inspections).toHaveBeenCalledTimes(33); + }, { timeout: 5000 }); + await quiet(); }); it("keeps unknown historical resources scheduled until provider confirmation", async () => { const lease = await pending(); await environmentService(db).releaseLease(lease.id, "failed", { cleanupStatus: "success" });