From ba1df26792901dca6a19f26cc4772941d72e15e9 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Mon, 2 Feb 2026 13:57:57 -0800 Subject: [PATCH] fix tests --- .../api/v1/external-db-sync-advanced.test.ts | 4 +++- .../api/v1/external-db-sync-race.test.ts | 8 ++++++-- .../api/v1/external-db-sync-utils.ts | 20 +++++++++++++------ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-advanced.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-advanced.test.ts index b0c6413f0..56869be1e 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-advanced.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-advanced.test.ts @@ -17,6 +17,8 @@ import { waitForTable } from './external-db-sync-utils'; +const COMPLEX_SEQUENCE_TIMEOUT = TEST_TIMEOUT * 2 + 30_000; + describe.sequential('External DB Sync - Advanced Tests', () => { let dbManager: TestDbManager; @@ -545,7 +547,7 @@ describe.sequential('External DB Sync - Advanced Tests', () => { const user2Row = res.rows.find(r => r.primary_email === 'seq2@example.com'); expect(user2Row.display_name).toBe('User 2 Updated'); - }, TEST_TIMEOUT); + }, COMPLEX_SEQUENCE_TIMEOUT); /** * What it does: diff --git a/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-race.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-race.test.ts index 5cf98e517..53b2c409a 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-race.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-race.test.ts @@ -10,6 +10,7 @@ import { TEST_TIMEOUT, TestDbManager, createProjectWithExternalDb, + forceExternalDbSync, waitForCondition, waitForSyncedDeletion, waitForTable @@ -271,7 +272,7 @@ describe.sequential('External DB Sync - Race Condition Tests', () => { * - Tests that sync captures all committed changes eventually */ describe('Race conditions with overlapping transactions', () => { - const LOCAL_TEST_TIMEOUT = 120_000; // Must be > 70s sleep + setup time + const LOCAL_TEST_TIMEOUT = TEST_TIMEOUT + 60_000; // Must cover baseline sync + fallback sleep on slow CI async function setupExternalDbWithBaseline(dbName: string) { const connectionString = await dbManager.createDatabase(dbName); @@ -365,7 +366,10 @@ describe.sequential('External DB Sync - Race Condition Tests', () => { [user.userId], ); - await sleep(70000); + const forced = await forceExternalDbSync(); + if (!forced) { + await sleep(70000); + } const during = await externalClient.query<{ display_name: string | null, diff --git a/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-utils.ts b/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-utils.ts index a49bfa4c3..10633e9b8 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-utils.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-utils.ts @@ -161,18 +161,16 @@ export async function waitForCondition( throw new Error(`Timeout waiting for ${description} after ${timeoutMs}ms`); } -async function maybeForceExternalDbSync() { - if (!SHOULD_FORCE_EXTERNAL_DB_SYNC) return; - - const now = performance.now(); - if (now - lastForcedSyncAt < FORCE_SYNC_INTERVAL_MS) return; - lastForcedSyncAt = now; +export async function forceExternalDbSync(): Promise { + if (!SHOULD_FORCE_EXTERNAL_DB_SYNC) return false; const cronSecret = process.env.CRON_SECRET; if (!cronSecret) { throw new Error('CRON_SECRET is required when STACK_FORCE_EXTERNAL_DB_SYNC=true'); } + lastForcedSyncAt = performance.now(); + await niceFetch(new URL('/api/latest/internal/external-db-sync/sequencer', STACK_BACKEND_BASE_URL), { query: { maxDurationMs: String(FORCE_SYNC_MAX_DURATION_MS), @@ -191,6 +189,16 @@ async function maybeForceExternalDbSync() { Authorization: `Bearer ${cronSecret}`, }, }); + return true; +} + +async function maybeForceExternalDbSync() { + if (!SHOULD_FORCE_EXTERNAL_DB_SYNC) return; + + const now = performance.now(); + if (now - lastForcedSyncAt < FORCE_SYNC_INTERVAL_MS) return; + + await forceExternalDbSync(); } /**