feat: DWH connectivity probe at startup — modal alert within 5s if unreachable

Backend: GET /health/dwh (unauthenticated) calls tht db ping with a 5s
timeout. Frontend: checkDwhHealth() races a 5s timer against the fetch;
on failure a non-dismissable Dialog with Retry appears immediately.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 13:59:11 +02:00
co-authored by Claude Opus 4.6
parent 83942c0b5c
commit 3b52c8c08c
7 changed files with 60 additions and 7 deletions
+2 -1
View File
@@ -86,10 +86,11 @@ export function buildApp(config: AppConfig, deps?: BuildAppDeps): FastifyInstanc
const authenticate = authPreHandler(config.authMode);
app.addHook("preHandler", async (req, reply) => {
// Process readiness is intentionally unauthenticated for local container/proxy probes.
if (req.url === "/health") return;
if (req.url === "/health" || req.url === "/health/dwh") return;
return authenticate(req, reply);
});
app.get("/health", async () => ({ status: "ok" }));
app.get("/health/dwh", async () => tht.dbPing());
app.get("/me", async (req) => getPrincipal(req));
sessionRoutes(app, {
mgr, tht: tht as ThtRunner, hub, getSettings, readiness, dwhPrecheck: config.dwhPrecheck,
+1 -1
View File
@@ -14,7 +14,7 @@ const READINESS_FAILURE_MESSAGE =
const RESUME_FAILURE_MESSAGE =
"Session could not be resumed. Check configuration and connectivity, then try again.";
const DWH_UNREACHABLE_MESSAGE =
"Cannot start a session: the data warehouse is unreachable. Check the VPN connection and try again.";
"Cannot start a session: the database is unreachable. Check the VPN connection and try again.";
export function sessionRoutes(
app: FastifyInstance,
+1 -1
View File
@@ -154,7 +154,7 @@ export class ThtRunner {
* cleanly. Timed out to keep POST /sessions responsive when the host hangs.
*/
async dbPing(workspace?: string): Promise<{ ok: boolean; detail: string }> {
const { code, stdout, stderr } = await this.run(["db", "ping"], workspace, 10_000);
const { code, stdout, stderr } = await this.run(["db", "ping"], workspace, 5_000);
if (code === 0) return { ok: true, detail: stdout.trim() };
return { ok: false, detail: (stderr || stdout).trim() };
}