portail-associations/server/_core/runtime.ts

78 lines
1.9 KiB
TypeScript

import fs from "node:fs/promises";
import path from "node:path";
import { getDb, isDatabaseConfigured } from "../db";
import { ENV } from "./env";
type RuntimeHealthState = "starting" | "ready" | "maintenance" | "shutting_down";
const startedAt = Date.now();
let ready = false;
let shuttingDown = false;
function resolveMaintenanceFlagPath() {
return path.resolve(ENV.maintenanceFlagPath || path.join(process.cwd(), "uploads/system/maintenance.flag"));
}
async function fileExists(filePath: string) {
try {
await fs.access(filePath);
return true;
} catch {
return false;
}
}
export function markRuntimeReady() {
ready = true;
}
export function markRuntimeShuttingDown() {
shuttingDown = true;
ready = false;
}
export async function isMaintenanceModeEnabled() {
return fileExists(resolveMaintenanceFlagPath());
}
export async function buildRuntimeHealth() {
const uptimeMs = Date.now() - startedAt;
const db = await getDb();
const databaseOk = !isDatabaseConfigured() || Boolean(db);
const startupDelaySatisfied = uptimeMs >= ENV.appReadyDelayMs;
const maintenance = await isMaintenanceModeEnabled();
let state: RuntimeHealthState = "starting";
if (shuttingDown) {
state = "shutting_down";
} else if (maintenance) {
state = "maintenance";
} else if (ready && startupDelaySatisfied && databaseOk) {
state = "ready";
}
const ok = state === "ready" || state === "maintenance";
return {
ok,
state,
service: "portail-associations",
environment: process.env.NODE_ENV || "development",
timestamp: new Date().toISOString(),
uptimeMs,
maintenance,
checks: {
startupDelaySatisfied,
databaseConfigured: isDatabaseConfigured(),
databaseOk,
ready,
shuttingDown,
},
};
}
export async function ensureMaintenanceFlagDirectory() {
const filePath = resolveMaintenanceFlagPath();
await fs.mkdir(path.dirname(filePath), { recursive: true });
return filePath;
}