Der Worker hängt am Discord-Gateway und schreibt alle 30 Sekunden sein Lebenszeichen in die Datenbank, damit /api/health im Web-Container den Gateway-Zustand kennt, ohne selbst mit Discord zu sprechen. healthcheck.js prüft genau dieses Lebenszeichen. Der eigentliche Rollen-Abgleich kommt in Phase 1. Der PDF-Dienst rendert die Druckansicht über Playwright. Kein PDF-Layout von Hand, die Gestaltung kommt aus @media print der Seite selbst. Er kennt keine Rechte: wer darf, entscheidet die Web-App, bevor sie hier anfragt, und schickt das Sitzungs-Cookie des Abrufers mit, damit die gerenderte Seite dessen Freigabestufe sieht.
40 lines
1.2 KiB
JavaScript
40 lines
1.2 KiB
JavaScript
// Healthcheck des Dienstes `worker`, wird vom Compose aufgerufen.
|
|
// Prueft das eigene Lebenszeichen in der Datenbank: ist es frisch und meldet
|
|
// `up`, gilt die Gateway-Verbindung als in Ordnung. Siehe docs/11-betrieb.md.
|
|
// `pg` wird als CommonJS ausgeliefert, deshalb der Default-Import.
|
|
import pg from 'pg'
|
|
|
|
const { Client } = pg
|
|
|
|
const MAX_AGE_MS = 120_000
|
|
|
|
const client = new Client({ connectionString: process.env.DIRECT_DATABASE_URL ?? process.env.DATABASE_URL })
|
|
|
|
try {
|
|
await client.connect()
|
|
const { rows } = await client.query(
|
|
'SELECT status, at FROM "ServiceHeartbeat" WHERE service = $1',
|
|
['worker'],
|
|
)
|
|
const beat = rows[0]
|
|
if (!beat) {
|
|
console.error('kein Lebenszeichen')
|
|
process.exit(1)
|
|
}
|
|
const ageMs = Date.now() - new Date(beat.at).getTime()
|
|
if (ageMs > MAX_AGE_MS) {
|
|
console.error(`Lebenszeichen ${Math.round(ageMs / 1000)} s alt`)
|
|
process.exit(1)
|
|
}
|
|
if (beat.status !== 'up') {
|
|
console.error(`Zustand ${beat.status}`)
|
|
process.exit(1)
|
|
}
|
|
process.exit(0)
|
|
} catch (error) {
|
|
console.error(error instanceof Error ? error.message : error)
|
|
process.exit(1)
|
|
} finally {
|
|
await client.end().catch(() => undefined)
|
|
}
|