Files

60 lines
1.6 KiB
JavaScript

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
};