Skip to content

Commit c0eb01e

Browse files
authored
Merge branch 'external-db-sync' into external-db-sync-a-2
2 parents 5328c5d + 093eaf0 commit c0eb01e

5 files changed

Lines changed: 61 additions & 17 deletions

File tree

apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-advanced.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
POSTGRES_USER,
1010
TEST_TIMEOUT,
1111
TestDbManager,
12-
createProjectWithExternalDb,
12+
createProjectWithExternalDb as createProjectWithExternalDbRaw,
1313
verifyNotInExternalDb,
1414
waitForCondition,
1515
waitForSyncedData,
@@ -21,6 +21,16 @@ const COMPLEX_SEQUENCE_TIMEOUT = TEST_TIMEOUT * 2 + 30_000;
2121

2222
describe.sequential('External DB Sync - Advanced Tests', () => {
2323
let dbManager: TestDbManager;
24+
const createProjectWithExternalDb = (
25+
externalDatabases: any,
26+
projectOptions?: { display_name?: string, description?: string }
27+
) => {
28+
return createProjectWithExternalDbRaw(
29+
externalDatabases,
30+
projectOptions,
31+
{ projectTracker: dbManager.createdProjects }
32+
);
33+
};
2434

2535
beforeAll(async () => {
2636
dbManager = new TestDbManager();

apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-basics.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { User, niceBackendFetch } from '../../../backend-helpers';
44
import {
55
TEST_TIMEOUT,
66
TestDbManager,
7-
createProjectWithExternalDb,
7+
createProjectWithExternalDb as createProjectWithExternalDbRaw,
88
verifyInExternalDb,
99
verifyNotInExternalDb,
1010
waitForCondition,
@@ -16,6 +16,16 @@ import {
1616
// Run tests sequentially to avoid concurrency issues with shared backend state
1717
describe.sequential('External DB Sync - Basic Tests', () => {
1818
let dbManager: TestDbManager;
19+
const createProjectWithExternalDb = (
20+
externalDatabases: any,
21+
projectOptions?: { display_name?: string, description?: string }
22+
) => {
23+
return createProjectWithExternalDbRaw(
24+
externalDatabases,
25+
projectOptions,
26+
{ projectTracker: dbManager.createdProjects }
27+
);
28+
};
1929

2030
beforeAll(async () => {
2131
dbManager = new TestDbManager();

apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-high-volume.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,24 @@ import {
88
POSTGRES_PASSWORD,
99
POSTGRES_USER,
1010
TestDbManager,
11-
createProjectWithExternalDb,
11+
createProjectWithExternalDb as createProjectWithExternalDbRaw,
1212
waitForCondition,
1313
waitForTable,
1414
} from './external-db-sync-utils';
1515

1616
// Run tests sequentially to avoid concurrency issues with shared backend state
1717
describe.sequential('External DB Sync - High Volume Tests', () => {
1818
let dbManager: TestDbManager;
19+
const createProjectWithExternalDb = (
20+
externalDatabases: any,
21+
projectOptions?: { display_name?: string, description?: string }
22+
) => {
23+
return createProjectWithExternalDbRaw(
24+
externalDatabases,
25+
projectOptions,
26+
{ projectTracker: dbManager.createdProjects }
27+
);
28+
};
1929

2030
beforeAll(async () => {
2131
dbManager = new TestDbManager();

apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-race.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
POSTGRES_USER,
1010
TEST_TIMEOUT,
1111
TestDbManager,
12-
createProjectWithExternalDb,
12+
createProjectWithExternalDb as createProjectWithExternalDbRaw,
1313
forceExternalDbSync,
1414
waitForCondition,
1515
waitForSyncedDeletion,
@@ -20,6 +20,16 @@ const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
2020

2121
describe.sequential('External DB Sync - Race Condition Tests', () => {
2222
let dbManager: TestDbManager;
23+
const createProjectWithExternalDb = (
24+
externalDatabases: any,
25+
projectOptions?: { display_name?: string, description?: string }
26+
) => {
27+
return createProjectWithExternalDbRaw(
28+
externalDatabases,
29+
projectOptions,
30+
{ projectTracker: dbManager.createdProjects }
31+
);
32+
};
2333

2434
beforeAll(async () => {
2535
dbManager = new TestDbManager();

apps/e2e/tests/backend/endpoints/api/v1/external-db-sync-utils.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,10 @@ const CLIENT_CONFIG: Partial<ClientConfig> = {
3737
};
3838

3939
// Track all projects created with external DB configs for cleanup
40-
type ProjectContext = {
40+
export type ProjectContext = {
4141
projectId: string,
4242
superSecretAdminKey: string,
4343
};
44-
const createdProjects: ProjectContext[] = [];
4544

4645
/**
4746
* Helper class to manage external test databases
@@ -50,6 +49,7 @@ export class TestDbManager {
5049
private setupClient: Client | null = null;
5150
private databases: Map<string, Client> = new Map();
5251
private databaseNames: Set<string> = new Set();
52+
public readonly createdProjects: ProjectContext[] = [];
5353

5454
async init() {
5555
this.setupClient = new Client({
@@ -84,7 +84,8 @@ export class TestDbManager {
8484

8585
async cleanup() {
8686
// First, clean up all project configs to stop the sync cron from trying to connect
87-
await cleanupAllProjectConfigs();
87+
await cleanupProjectConfigs(this.createdProjects);
88+
this.createdProjects.length = 0;
8889

8990
// Close all tracked database clients
9091
const closePromises = Array.from(this.databases.values()).map(async (client) => {
@@ -365,7 +366,11 @@ export async function countUsersInExternalDb(client: Client): Promise<number> {
365366
* Helper to create a project and update its config with external DB settings.
366367
* Tracks the project for cleanup later.
367368
*/
368-
export async function createProjectWithExternalDb(externalDatabases: any, projectOptions?: { display_name?: string, description?: string }) {
369+
export async function createProjectWithExternalDb(
370+
externalDatabases: any,
371+
projectOptions?: { display_name?: string, description?: string },
372+
options?: { projectTracker?: ProjectContext[] }
373+
) {
369374
const project = await Project.createAndSwitch(projectOptions);
370375
const { projectKeys } = await InternalApiKey.createAndSetProjectKeys(project.adminAccessToken);
371376
if (!projectKeys.superSecretAdminKey) {
@@ -376,10 +381,12 @@ export async function createProjectWithExternalDb(externalDatabases: any, projec
376381
});
377382

378383
// Track this project for cleanup
379-
createdProjects.push({
380-
projectId: project.projectId,
381-
superSecretAdminKey: projectKeys.superSecretAdminKey,
382-
});
384+
if (options?.projectTracker) {
385+
options.projectTracker.push({
386+
projectId: project.projectId,
387+
superSecretAdminKey: projectKeys.superSecretAdminKey,
388+
});
389+
}
383390

384391
return project;
385392
}
@@ -400,8 +407,8 @@ export async function cleanupProjectExternalDb() {
400407
* Note: This function makes direct HTTP calls instead of using backendContext
401408
* because it runs in afterAll, which is outside the test context.
402409
*/
403-
export async function cleanupAllProjectConfigs() {
404-
for (const project of createdProjects) {
410+
export async function cleanupProjectConfigs(projects: ProjectContext[]) {
411+
for (const project of projects) {
405412
try {
406413
// Make direct HTTP call to clear the external DB config
407414
await niceFetch(new URL('/api/latest/internal/config/override', STACK_BACKEND_BASE_URL), {
@@ -421,7 +428,4 @@ export async function cleanupAllProjectConfigs() {
421428
console.warn(`Failed to cleanup project ${project.projectId}:`, err);
422429
}
423430
}
424-
425-
// Clear the tracked projects
426-
createdProjects.length = 0;
427431
}

0 commit comments

Comments
 (0)