// 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 README, Betrieb. // `pg` wird als CommonJS ausgeliefert, deshalb der Default-Import. import pg from 'pg' const { Client } = pg 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, 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 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') { 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) }