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 { Hono } from 'hono'
import { cors } from 'hono/cors'
import { serve } from '@hono/node-server'
import { createNodeWebSocket } from '@hono/node-ws'
import authRoutes from './routes/auth.js'
import plansRoutes from './routes/plans.js'
import simulationsRoutes from './routes/simulations.js'
import sujetsRoutes from './routes/sujets.js'
import correctionsRoutes from './routes/corrections.js'
import stripeRoutes from './routes/stripe.js'
import createT2LiveRoutes from './routes/t2live.js'
import usersRoutes from './routes/users.js'
import "dotenv/config";
import { Hono } from "hono";
import { cors } from "hono/cors";
import { serve } from "@hono/node-server";
import { createNodeWebSocket } from "@hono/node-ws";
import authRoutes from "./routes/auth.js";
import plansRoutes from "./routes/plans.js";
import simulationsRoutes from "./routes/simulations.js";
import sujetsRoutes from "./routes/sujets.js";
import correctionsRoutes from "./routes/corrections.js";
import stripeRoutes from "./routes/stripe.js";
import createT2LiveRoutes from "./routes/t2live.js";
import usersRoutes from "./routes/users.js";
import { supabase } from "./lib/supabase.js";
const app = new Hono()
const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app })
const app = new Hono();
const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app });
app.use(
'*',
"*",
cors({
origin: [
'https://expria.app',
'http://localhost:5173',
'http://localhost:5174',
"https://expria.app",
"http://localhost:5173",
"http://localhost:5174",
],
allowMethods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization', 'X-Api-Version'],
})
)
allowMethods: ["GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS"],
allowHeaders: ["Content-Type", "Authorization", "X-Api-Version"],
}),
);
app.get('/', (c) => {
return c.json({ message: 'Expria API — OK' }, 200)
})
// Health check — exécute un SELECT 1 léger sur Supabase pour garder le pool
// 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.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)
app.get("/", async (c) => {
const probe = supabase.from("profiles").select("id", { head: true }).limit(1);
const timeout = new Promise<{ error: Error }>((resolve) =>
setTimeout(
() => resolve({ error: new Error("HEALTH_DB_TIMEOUT") }),
HEALTH_DB_TIMEOUT_MS,
),
);
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 }, () => {
console.log(`Expria API listening on port ${port}`)
})
console.log(`Expria API listening on port ${port}`);
});
injectWebSocket(server)
injectWebSocket(server);