diff --git a/worker/healthcheck.js b/worker/healthcheck.js index 8984232..80a67af 100644 --- a/worker/healthcheck.js +++ b/worker/healthcheck.js @@ -1,29 +1,47 @@ // 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. +// `up`, gilt die Gateway-Verbindung als in Ordnung. Siehe README, Betrieb. // `pg` wird als CommonJS ausgeliefert, deshalb der Default-Import. import pg from 'pg' const { Client } = pg -const MAX_AGE_MS = 120_000 +const MAX_AGE_S = 120 const client = new Client({ connectionString: process.env.DIRECT_DATABASE_URL ?? process.env.DATABASE_URL }) try { await client.connect() + + // Das Alter wird **in der Datenbank** gerechnet und nicht in JavaScript. + // + // `at` ist ein `timestamp` ohne Zeitzone, und Prisma schreibt UTC hinein. + // node-postgres liest so einen Wert aber als *lokale* Zeit; im Container + // steht TZ=Europe/Berlin, und damit war jedes Lebenszeichen beim Lesen + // schlagartig zwei Stunden alt - der Dienst galt dauerhaft als krank, + // obwohl er im Sekundentakt schrieb. + // + // `now() AT TIME ZONE 'UTC'` liefert die aktuelle UTC-Wanduhrzeit als + // zeitzonenlosen Wert, also genau in der Form, in der `at` gespeichert ist. + // Die Rechnung stimmt damit unabhaengig davon, welche Zeitzone im Container + // oder in der Datenbank eingestellt ist. const { rows } = await client.query( - 'SELECT status, at FROM "ServiceHeartbeat" WHERE service = $1', + `SELECT status, + EXTRACT(EPOCH FROM (now() AT TIME ZONE 'UTC' - at)) AS alter_s + 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`) + + const alter = Math.round(Number(beat.alter_s)) + if (alter > MAX_AGE_S) { + console.error(`Lebenszeichen ${alter} s alt`) process.exit(1) } if (beat.status !== 'up') {