fix(tracker-web): probe platform health
This commit is contained in:
parent
325dfcae8e
commit
e25969d5dc
@ -2,7 +2,7 @@
|
|||||||
* Tests for GET /api/health (tracker dashboard)
|
* Tests for GET /api/health (tracker dashboard)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, it, expect, afterEach } from 'vitest';
|
import { describe, it, expect, afterEach, vi } from 'vitest';
|
||||||
|
|
||||||
import { GET } from '@/app/api/health/route';
|
import { GET } from '@/app/api/health/route';
|
||||||
|
|
||||||
@ -11,12 +11,17 @@ describe('GET /api/health', () => {
|
|||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
process.env = { ...originalEnv };
|
process.env = { ...originalEnv };
|
||||||
|
vi.unstubAllGlobals();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns ok when all required env vars are set', async () => {
|
it('returns ok when all required env vars are set and platform-service is healthy', async () => {
|
||||||
process.env.PLATFORM_API_URL = 'http://localhost:4003';
|
process.env.PLATFORM_API_URL = 'http://localhost:4003';
|
||||||
process.env.JWT_SECRET = 'test-secret';
|
process.env.JWT_SECRET = 'test-secret';
|
||||||
process.env.DEFAULT_PRODUCT_ID = 'test-product';
|
process.env.DEFAULT_PRODUCT_ID = 'test-product';
|
||||||
|
vi.stubGlobal(
|
||||||
|
'fetch',
|
||||||
|
vi.fn(async () => new Response(JSON.stringify({ status: 'ok' }), { status: 200 }))
|
||||||
|
);
|
||||||
|
|
||||||
const res = await GET();
|
const res = await GET();
|
||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
@ -30,7 +35,33 @@ describe('GET /api/health', () => {
|
|||||||
status: 'pass',
|
status: 'pass',
|
||||||
message: '3 required vars set',
|
message: '3 required vars set',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'platform-service',
|
||||||
|
status: 'pass',
|
||||||
|
message: 'healthy',
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
expect(fetch).toHaveBeenCalledWith('http://localhost:4003/health', expect.any(Object));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns degraded when platform-service health check fails', async () => {
|
||||||
|
process.env.PLATFORM_API_URL = 'http://localhost:4003';
|
||||||
|
process.env.JWT_SECRET = 'test-secret';
|
||||||
|
process.env.DEFAULT_PRODUCT_ID = 'test-product';
|
||||||
|
vi.stubGlobal(
|
||||||
|
'fetch',
|
||||||
|
vi.fn(async () => new Response(JSON.stringify({ status: 'degraded' }), { status: 503 }))
|
||||||
|
);
|
||||||
|
|
||||||
|
const res = await GET();
|
||||||
|
expect(res.status).toBe(503);
|
||||||
|
const data = await res.json();
|
||||||
|
expect(data.status).toBe('degraded');
|
||||||
|
expect(data.checks).toContainEqual({
|
||||||
|
name: 'platform-service',
|
||||||
|
status: 'fail',
|
||||||
|
message: 'HTTP 503',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns degraded when env vars are missing', async () => {
|
it('returns degraded when env vars are missing', async () => {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ interface Check {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const REQUIRED_ENV = ['PLATFORM_API_URL', 'JWT_SECRET', 'DEFAULT_PRODUCT_ID'];
|
const REQUIRED_ENV = ['PLATFORM_API_URL', 'JWT_SECRET', 'DEFAULT_PRODUCT_ID'];
|
||||||
|
const PLATFORM_HEALTH_TIMEOUT_MS = 2_000;
|
||||||
|
|
||||||
function checkEnvVars(): Check {
|
function checkEnvVars(): Check {
|
||||||
const missing = REQUIRED_ENV.filter(key => !process.env[key]);
|
const missing = REQUIRED_ENV.filter(key => !process.env[key]);
|
||||||
@ -16,10 +17,42 @@ function checkEnvVars(): Check {
|
|||||||
return { name: 'env', status: 'pass', message: `${REQUIRED_ENV.length} required vars set` };
|
return { name: 'env', status: 'pass', message: `${REQUIRED_ENV.length} required vars set` };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkPlatformService(): Promise<Check> {
|
||||||
|
const baseUrl = process.env.PLATFORM_API_URL;
|
||||||
|
if (!baseUrl) {
|
||||||
|
return { name: 'platform-service', status: 'fail', message: 'PLATFORM_API_URL missing' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), PLATFORM_HEALTH_TIMEOUT_MS);
|
||||||
|
try {
|
||||||
|
const res = await fetch(new URL('/health', baseUrl).toString(), {
|
||||||
|
cache: 'no-store',
|
||||||
|
signal: controller.signal,
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
return { name: 'platform-service', status: 'fail', message: `HTTP ${res.status}` };
|
||||||
|
}
|
||||||
|
return { name: 'platform-service', status: 'pass', message: 'healthy' };
|
||||||
|
} catch (err) {
|
||||||
|
return {
|
||||||
|
name: 'platform-service',
|
||||||
|
status: 'fail',
|
||||||
|
message: err instanceof Error ? err.message : 'health check failed',
|
||||||
|
};
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
const checks: Check[] = [];
|
const checks: Check[] = [];
|
||||||
|
|
||||||
checks.push(checkEnvVars());
|
const envCheck = checkEnvVars();
|
||||||
|
checks.push(envCheck);
|
||||||
|
if (envCheck.status === 'pass') {
|
||||||
|
checks.push(await checkPlatformService());
|
||||||
|
}
|
||||||
|
|
||||||
const overall = checks.every(c => c.status === 'pass') ? 'ok' : 'degraded';
|
const overall = checks.every(c => c.status === 'pass') ? 'ok' : 'degraded';
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user