← back to Homesonspec

apps/admin/src/app/api/engine-log/route.ts

36 lines

import { NextResponse } from "next/server";
import { open, stat } from "node:fs/promises";

export const dynamic = "force-dynamic";

// Live tail of the ingestion ENGINE (pm2 homesonspec-ingest build-loop). The admin runs on the
// same Kamatera box as the engine, so it reads the pm2 out-log directly. Bounded tail (last ~56KB)
// so a huge/rotated log never blows memory. Read-only.
const LOG = "/root/.pm2/logs/homesonspec-ingest-out.log";
const TAIL_BYTES = 56 * 1024;

async function tail(path: string): Promise<string> {
  const st = await stat(path);
  const start = Math.max(0, st.size - TAIL_BYTES);
  const len = st.size - start;
  const fh = await open(path, "r");
  try {
    const buf = Buffer.alloc(len);
    await fh.read(buf, 0, len, start);
    return buf.toString("utf8");
  } finally {
    await fh.close();
  }
}

export async function GET() {
  try {
    const raw = await tail(LOG);
    // drop the first (likely partial) line, keep the last ~200
    const lines = raw.split("\n").slice(1).filter(Boolean).slice(-200);
    return NextResponse.json({ ts: new Date().toISOString(), ok: true, lines });
  } catch (e: any) {
    return NextResponse.json({ ts: new Date().toISOString(), ok: false, error: String(e?.message ?? e), lines: [] });
  }
}