fix(health): add Supabase keepalive ping to GET / health check

UptimeRobot pings GET / every 5 minutes. Previously static response
only kept Node process alive but let Supabase connection pool go cold.
Now executes a lightweight HEAD query (profiles, limit 1) to maintain
DB connection warmth. Always returns 200 with db status field for
observability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hermann_Kitio 2026-04-25 02:07:27 +03:00
parent b5980ccce2
commit fa06daace8

View file

@ -1,50 +1,71 @@
import 'dotenv/config' import "dotenv/config";
import { Hono } from 'hono' import { Hono } from "hono";
import { cors } from 'hono/cors' import { cors } from "hono/cors";
import { serve } from '@hono/node-server' import { serve } from "@hono/node-server";
import { createNodeWebSocket } from '@hono/node-ws' import { createNodeWebSocket } from "@hono/node-ws";
import authRoutes from './routes/auth.js' import authRoutes from "./routes/auth.js";
import plansRoutes from './routes/plans.js' import plansRoutes from "./routes/plans.js";
import simulationsRoutes from './routes/simulations.js' import simulationsRoutes from "./routes/simulations.js";
import sujetsRoutes from './routes/sujets.js' import sujetsRoutes from "./routes/sujets.js";
import correctionsRoutes from './routes/corrections.js' import correctionsRoutes from "./routes/corrections.js";
import stripeRoutes from './routes/stripe.js' import stripeRoutes from "./routes/stripe.js";
import createT2LiveRoutes from './routes/t2live.js' import createT2LiveRoutes from "./routes/t2live.js";
import usersRoutes from './routes/users.js' import usersRoutes from "./routes/users.js";
import { supabase } from "./lib/supabase.js";
const app = new Hono() const app = new Hono();
const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app }) const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app });
app.use( app.use(
'*', "*",
cors({ cors({
origin: [ origin: [
'https://expria.app', "https://expria.app",
'http://localhost:5173', "http://localhost:5173",
'http://localhost:5174', "http://localhost:5174",
], ],
allowMethods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'], allowMethods: ["GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS"],
allowHeaders: ['Content-Type', 'Authorization', 'X-Api-Version'], allowHeaders: ["Content-Type", "Authorization", "X-Api-Version"],
}) }),
) );
app.get('/', (c) => { // Health check — exécute un SELECT 1 léger sur Supabase pour garder le pool
return c.json({ message: 'Expria API — OK' }, 200) // de connexions DB actif (ping UptimeRobot toutes les 5 min sur Render Starter).
}) // Le endpoint retourne toujours 200 (liveness) ; le champ `db` reporte l'état
// réel de la connexion pour observabilité.
const HEALTH_DB_TIMEOUT_MS = 5000;
app.route('/auth', authRoutes) app.get("/", async (c) => {
app.route('/plans', plansRoutes) const probe = supabase.from("profiles").select("id", { head: true }).limit(1);
app.route('/simulations', simulationsRoutes) const timeout = new Promise<{ error: Error }>((resolve) =>
app.route('/sujets', sujetsRoutes) setTimeout(
app.route('/corrections', correctionsRoutes) () => resolve({ error: new Error("HEALTH_DB_TIMEOUT") }),
app.route('/stripe', stripeRoutes) HEALTH_DB_TIMEOUT_MS,
app.route('/t2', createT2LiveRoutes(upgradeWebSocket)) ),
app.route('/users', usersRoutes) );
const port = Number(process.env.PORT) || 3000 try {
const result = await Promise.race([probe, timeout]);
const db = "error" in result && result.error ? "error" : "connected";
return c.json({ message: "Expria API — OK", db }, 200);
} catch {
return c.json({ message: "Expria API — OK", db: "error" }, 200);
}
});
app.route("/auth", authRoutes);
app.route("/plans", plansRoutes);
app.route("/simulations", simulationsRoutes);
app.route("/sujets", sujetsRoutes);
app.route("/corrections", correctionsRoutes);
app.route("/stripe", stripeRoutes);
app.route("/t2", createT2LiveRoutes(upgradeWebSocket));
app.route("/users", usersRoutes);
const port = Number(process.env.PORT) || 3000;
const server = serve({ fetch: app.fetch, port }, () => { const server = serve({ fetch: app.fetch, port }, () => {
console.log(`Expria API listening on port ${port}`) console.log(`Expria API listening on port ${port}`);
}) });
injectWebSocket(server) injectWebSocket(server);