Ctrl K
ComunidadGuías…

start.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/**
 * Container entrypoint.
 *
 * Three parts in one process tree: Next on a loopback port, the document
 * server on another, and the proxy in this process on the public port. If a
 * child exits, everything exits, so the container restarts a whole system
 * rather than leaving half of one running.
 */
import { spawn } from "node:child_process";
import { startProxy } from "./proxy.mjs";

const PORT = Number(process.env.PORT || 1936);
const APP_PORT = Number(process.env.INDY_APP_PORT || 3100);
const COLLAB_PORT = Number(process.env.COLLAB_PORT || 3101);
const APP_ENTRY = process.env.INDY_APP_ENTRY || "/app/app/server.js";
const COLLAB_ENTRY = process.env.INDY_COLLAB_ENTRY || "/app/collab/server.mjs";

const children = new Map();
let proxy = null;
let stopping = false;

/** Resolves when the child has exited, killing it outright once `ms` have passed. */
function exited(child, ms) {
  return new Promise((resolve) => {
    if (child.exitCode !== null || child.signalCode !== null) return resolve();
    const timer = setTimeout(() => {
      child.kill("SIGKILL");
      resolve();
    }, ms);
    child.once("exit", () => {
      clearTimeout(timer);
      resolve();
    });
  });
}

/**
 * Shut down in order, inside Docker's ten-second grace period: stop taking
 * requests, then stop the document server while the app is still up, so it
 * can save open documents and hand its last edits to the app as versions,
 * then stop the app.
 */
async function stop(code) {
  if (stopping) return;
  stopping = true;
  const deadline = Date.now() + 8000;
  proxy?.close();
  for (const name of ["documents", "app"]) {
    const child = children.get(name);
    if (!child) continue;
    if (child.exitCode === null && child.signalCode === null) child.kill("SIGTERM");
    await exited(child, Math.max(500, deadline - Date.now()));
  }
  process.exit(code);
}

function run(name, args, env) {
  const child = spawn(process.execPath, args, { stdio: "inherit", env: { ...process.env, ...env } });
  child.on("exit", (code, signal) => {
    console.log(`[indy] ${name} exited (code ${code}, signal ${signal})`);
    void stop(code ?? 1);
  });
  children.set(name, child);
}

process.on("SIGTERM", () => void stop(0));
process.on("SIGINT", () => void stop(0));

const shared = {
  COLLAB_PORT: String(COLLAB_PORT),
  INDY_COLLAB_URL: `http://127.0.0.1:${COLLAB_PORT}`,
  INDY_APP_URL: `http://127.0.0.1:${APP_PORT}`,
};
run("app", [APP_ENTRY], { ...shared, PORT: String(APP_PORT), HOSTNAME: "127.0.0.1" });
run("documents", [COLLAB_ENTRY], shared);
proxy = startProxy({ port: PORT, appPort: APP_PORT, collabPort: COLLAB_PORT });