60 lines
1.6 KiB
JavaScript
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
|
|
};
|