MCPcopy Create free account
hub / github.com/heygen-com/hyperframes / startServer

Function startServer

packages/producer/src/server.ts:728–797  ·  view source on GitHub ↗
(options: ServerOptions = {})

Source from the content-addressed store, hash-verified

726 * Start the producer HTTP server with graceful shutdown.
727 */
728export function startServer(options: ServerOptions = {}) {
729 const port = options.port ?? parseInt(process.env.PRODUCER_PORT ?? "9847", 10);
730 const log = options.logger ?? defaultLogger;
731 const app = createProducerApp(options);
732
733 const server = serve({ fetch: app.fetch, port }, () => {
734 log.info(`Listening on http://localhost:${port}`);
735 });
736
737 // Disable timeouts for long renders
738 server.setTimeout(0);
739 (server as unknown as import("node:http").Server).requestTimeout = 0;
740 (server as unknown as import("node:http").Server).keepAliveTimeout = 0;
741
742 // Start the worker-thread health endpoint alongside the main listener.
743 // The main thread keeps serving /health on `port` for backwards
744 // compatibility; the worker thread additionally serves /health on
745 // PRODUCER_HEALTH_PORT (default 9848) so k8s liveness/readiness probes can
746 // migrate to a listener that doesn't share an event loop with renders.
747 //
748 // Opt-out: set PRODUCER_DISABLE_HEALTH_WORKER=1 (e.g. for tests that don't
749 // want a worker spawned, or for environments where the extra port isn't
750 // wanted).
751 //
752 // We store the *promise* (not the resolved handle) so a SIGTERM that
753 // arrives before the worker has finished booting still has something to
754 // await. Awaiting a `let healthWorker = null` mutated from inside `.then`
755 // would race: if SIGTERM lands before the `.then` callback fires,
756 // `shutdown()` sees `null` and skips worker cleanup. The promise pattern
757 // closes that window without making startup blocking.
758 const healthWorkerPromise: Promise<HealthWorkerHandle | null> =
759 process.env.PRODUCER_DISABLE_HEALTH_WORKER === "1"
760 ? Promise.resolve(null)
761 : startHealthWorker({ logger: log }).catch((err: Error) => {
762 // Don't crash the producer if the worker fails to start — the main
763 // /health is still up. Log loudly so the operator notices.
764 log.error(`[server] health worker failed to start: ${err.message}`);
765 return null;
766 });
767
768 async function shutdown(signal: string) {
769 log.info(`Received ${signal}, shutting down`);
770 const { drainBrowserPool } = await import("@hyperframes/engine");
771 await drainBrowserPool().catch(() => {});
772 // Bounded await: if the worker hasn't come online within 1.5s of
773 // shutdown there's no useful cleanup left to do — `worker.terminate()`
774 // from process exit will kill the thread regardless, and we'd rather
775 // not let a hung-startup worker keep the SIGTERM path waiting.
776 const handle = await Promise.race<HealthWorkerHandle | null>([
777 healthWorkerPromise,
778 new Promise<null>((res) => setTimeout(() => res(null), 1_500).unref()),
779 ]);
780 if (handle) {
781 await handle.shutdown().catch(() => {});
782 }
783 server.close(() => {
784 log.info("Server closed");
785 process.exit(0);

Callers 1

server.tsFile · 0.70

Calls 7

createProducerAppFunction · 0.85
startHealthWorkerFunction · 0.85
infoMethod · 0.80
errorMethod · 0.80
shutdownFunction · 0.70
onMethod · 0.65
serveFunction · 0.50

Tested by

no test coverage detected