const fs = require('fs'); const DEFAULT_MIN_FREE_BYTES = 256 * 1024 * 1024; function normalizeMinimumFreeBytes(value) { const parsed = Number(value); return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : DEFAULT_MIN_FREE_BYTES; } function createHealthService({ db, diskPath, minimumFreeBytes = process.env.HEALTH_MIN_DISK_FREE_BYTES }) { const diskThreshold = normalizeMinimumFreeBytes(minimumFreeBytes); function checkDatabase() { const startedAt = process.hrtime.bigint(); try { const row = db.prepare('SELECT 1 AS ok').get(); return { status: row?.ok === 1 ? 'ok' : 'error', latencyMs: Number((Number(process.hrtime.bigint() - startedAt) / 1e6).toFixed(2)) }; } catch (error) { return { status: 'error', message: error.code || error.name || 'database_error' }; } } function checkDisk() { try { const stats = fs.statfsSync(diskPath); const freeBytes = Number(BigInt(stats.bavail) * BigInt(stats.bsize)); return { status: freeBytes >= diskThreshold ? 'ok' : 'low', freeBytes, minimumFreeBytes: diskThreshold }; } catch (error) { return { status: 'error', message: error.code || error.name || 'disk_error' }; } } function check() { const checks = { database: checkDatabase(), disk: checkDisk() }; const healthy = checks.database.status === 'ok' && checks.disk.status === 'ok'; return { healthy, status: healthy ? 'ok' : 'degraded', checks }; } return { check }; } module.exports = { createHealthService, normalizeMinimumFreeBytes };