65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
/**
|
|
* Test B — Gateway boot refuses (fail-fast) when PG is unreachable.
|
|
*
|
|
* Prereq: docker compose -f docker-compose.federated.yml --profile federated up -d
|
|
* (Valkey must be running; only PG is intentionally misconfigured.)
|
|
* Run: FEDERATED_INTEGRATION=1 pnpm --filter @mosaicstack/gateway test src/__tests__/integration/federated-boot.pg-unreachable.integration.test.ts
|
|
*
|
|
* Skipped when FEDERATED_INTEGRATION !== '1'.
|
|
*/
|
|
|
|
import net from 'node:net';
|
|
import { beforeAll, describe, expect, it } from 'vitest';
|
|
import { TierDetectionError, detectAndAssertTier } from '@mosaicstack/storage';
|
|
|
|
const run = process.env['FEDERATED_INTEGRATION'] === '1';
|
|
|
|
const VALKEY_URL = 'redis://localhost:6380';
|
|
|
|
/**
|
|
* Reserves a guaranteed-closed port at runtime by binding to an ephemeral OS
|
|
* port (port 0) and immediately releasing it. The OS will not reassign the
|
|
* port during the TIME_WAIT window, so it remains closed for the duration of
|
|
* this test.
|
|
*/
|
|
async function reserveClosedPort(): Promise<number> {
|
|
return new Promise((resolve, reject) => {
|
|
const server = net.createServer();
|
|
server.listen(0, '127.0.0.1', () => {
|
|
const addr = server.address();
|
|
if (typeof addr !== 'object' || !addr) return reject(new Error('no addr'));
|
|
const port = addr.port;
|
|
server.close(() => resolve(port));
|
|
});
|
|
server.on('error', reject);
|
|
});
|
|
}
|
|
|
|
describe.skipIf(!run)('federated boot — PG unreachable', () => {
|
|
let badPgUrl: string;
|
|
|
|
beforeAll(async () => {
|
|
const closedPort = await reserveClosedPort();
|
|
badPgUrl = `postgresql://mosaic:mosaic@localhost:${closedPort}/mosaic`;
|
|
});
|
|
|
|
it('detectAndAssertTier throws TierDetectionError with service: postgres when PG is down', async () => {
|
|
const brokenConfig = {
|
|
tier: 'federated' as const,
|
|
storage: {
|
|
type: 'postgres' as const,
|
|
url: badPgUrl,
|
|
enableVector: true,
|
|
},
|
|
queue: {
|
|
type: 'bullmq',
|
|
url: VALKEY_URL,
|
|
},
|
|
};
|
|
|
|
await expect(detectAndAssertTier(brokenConfig)).rejects.toSatisfy(
|
|
(err: unknown) => err instanceof TierDetectionError && err.service === 'postgres',
|
|
);
|
|
}, 10_000);
|
|
});
|