From b787120461ed4c6e0b2969840353f2eaf5d94dc7 Mon Sep 17 00:00:00 2001 From: Jackson Roberts Date: Fri, 27 Feb 2026 17:06:36 -0600 Subject: [PATCH] fix: start HTTP server before background init to prevent bad gateway --- src/index.ts | 88 +++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/src/index.ts b/src/index.ts index 1d650cf..5e9e596 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,30 +21,6 @@ import cuid from "cuid"; // Setup global event debugger in non-production environments if (Bun.env.NODE_ENV == "development") setupEventDebugger(); -// Ensure administrator role exists -const existingAdmin = await prisma.role.findFirst({ - where: { moniker: "administrator" }, - include: { users: { include: { roles: true } } }, -}); - -if (!existingAdmin) { - const id = cuid(); - const created = await prisma.role.create({ - data: { - id, - moniker: "administrator", - title: "Admin", - permissions: signPermissions({ - issuer: "roles", - subject: id, - permissions: ["*"], - }), - }, - include: { users: { include: { roles: true } } }, - }); - events.emit("role:created", new RoleController(created)); -} - // Helper to run a startup sync safely — failures are logged but never crash the process. const safeStartup = async (label: string, fn: () => Promise) => { try { @@ -57,6 +33,56 @@ const safeStartup = async (label: string, fn: () => Promise) => { } }; +// --------------------------------------------------------------------------- +// Start the HTTP server FIRST so the pod is reachable immediately. +// All data-sync tasks run afterwards and are non-blocking. +// --------------------------------------------------------------------------- +Bun.serve({ + port: PORT, + websocket: engine.handler().websocket, + fetch: (req, server) => { + const url = new URL(req.url); + + if (url.pathname.startsWith("/socket.io/")) { + return engine.handleRequest(req, server as any); + } + + return app.fetch(req, server); + }, +}); + +console.log(`[startup] Server listening on port ${PORT}`); + +// --------------------------------------------------------------------------- +// Background initialisation — none of this blocks the server. +// --------------------------------------------------------------------------- + +// Ensure administrator role exists +await safeStartup("ensureAdminRole", async () => { + const existingAdmin = await prisma.role.findFirst({ + where: { moniker: "administrator" }, + include: { users: { include: { roles: true } } }, + }); + + if (!existingAdmin) { + const id = cuid(); + const created = await prisma.role.create({ + data: { + id, + moniker: "administrator", + title: "Admin", + permissions: signPermissions({ + issuer: "roles", + subject: id, + permissions: ["*"], + }), + }, + include: { users: { include: { roles: true } } }, + }); + events.emit("role:created", new RoleController(created)); + } +}); + // Refresh the internal list of companies every minute await safeStartup("refreshCompanies", refreshCompanies); setInterval(() => { @@ -98,17 +124,3 @@ setInterval(() => { .syncSites() .catch((err) => console.error("[interval] syncSites failed", err)); }, 60 * 1000); - -Bun.serve({ - port: PORT, - websocket: engine.handler().websocket, - fetch: (req, server) => { - const url = new URL(req.url); - - if (url.pathname.startsWith("/socket.io/")) { - return engine.handleRequest(req, server as any); - } - - return app.fetch(req, server); - }, -});