From 08e8ffe1e84215303afafd0aa996d997b61cf2cf Mon Sep 17 00:00:00 2001 From: GreenEclipse Date: Mon, 10 Aug 2026 01:31:55 +0200 Subject: [PATCH] fix --- scripts/migrate.mjs | 110 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 11 deletions(-) diff --git a/scripts/migrate.mjs b/scripts/migrate.mjs index a0b3461..32640ed 100644 --- a/scripts/migrate.mjs +++ b/scripts/migrate.mjs @@ -1,14 +1,31 @@ #!/usr/bin/env node /** - * Cross-platform goose migrate + sqlc generate (Windows / macOS / Linux). + * Cross-platform goose migrate (+ optional sqlc generate). * Loads monorepo-root `.env` when DATABASE_URL is unset. * - * Usage: node scripts/migrate.mjs + * Usage: + * node scripts/migrate.mjs # goose only (default) + * node scripts/migrate.mjs --sqlc # also regenerate apps/api/internal/db/sqlc + * + * A 4GiB host is enough for goose + the app. sqlc's go-pgquery/wazero path + * allocates a ~4GiB WASM heap by itself, so it OOMs on 4GiB VPS — skip by + * default; only run --sqlc on a machine with ≥6GiB free (or install a + * prebuilt `sqlc` binary and still prefer ≥6GiB). */ import { spawnSync } from "node:child_process"; +import fs from "node:fs"; import path from "node:path"; import { loadRootEnv, repoRoot } from "./root-env.mjs"; +const args = new Set(process.argv.slice(2)); +const wantSqlc = + args.has("--sqlc") || + process.env.DESCRYBE_SQLC === "1" || + /^true|yes|on$/i.test(String(process.env.DESCRYBE_SQLC || "")); + +/** Prefer this much free/total RAM (MiB) before attempting sqlc go-run/wazero. */ +const SQLC_MIN_RAM_MIB = Number(process.env.DESCRYBE_SQLC_MIN_RAM_MIB || 6144); + const env = loadRootEnv(process.env); if (!env.DATABASE_URL) { console.error( @@ -19,8 +36,8 @@ if (!env.DATABASE_URL) { const apiDir = path.join(repoRoot, "apps", "api"); -function run(command, args, opts = {}) { - const r = spawnSync(command, args, { +function run(command, cmdArgs, opts = {}) { + const r = spawnSync(command, cmdArgs, { cwd: apiDir, env, stdio: "inherit", @@ -36,6 +53,41 @@ function run(command, args, opts = {}) { } } +/** Best-effort total RAM in MiB (Linux /proc, Windows wmic, or null). */ +function totalRamMiB() { + try { + if (process.platform === "linux") { + const text = fs.readFileSync("/proc/meminfo", "utf8"); + const m = text.match(/^MemTotal:\s+(\d+)\s+kB/m); + if (m) return Math.floor(Number(m[1]) / 1024); + } + if (process.platform === "win32") { + const r = spawnSync( + "powershell", + [ + "-NoProfile", + "-Command", + "[int]((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory/1MB)", + ], + { encoding: "utf8" }, + ); + const n = Number(String(r.stdout || "").trim()); + if (Number.isFinite(n) && n > 0) return n; + } + } catch { + /* ignore */ + } + return null; +} + +function hasSqlcBinary() { + const r = spawnSync("sqlc", ["version"], { + encoding: "utf8", + shell: process.platform === "win32", + }); + return !(r.error || r.status !== 0); +} + console.log("==> goose up (apps/api/sql/schema)"); run("go", [ "run", @@ -47,6 +99,29 @@ run("go", [ "up", ]); +if (!wantSqlc) { + console.log( + "==> sqlc skipped (default). 4GiB hosts: goose + app are enough; sqlc needs extra headroom.", + ); + console.log(" Regenerate on a larger machine: npm run migrate -- --sqlc"); + console.log("==> done"); + process.exit(0); +} + +const ram = totalRamMiB(); +if (ram != null && ram < SQLC_MIN_RAM_MIB && !hasSqlcBinary()) { + console.error( + `[migrate] refusing sqlc: ~${ram}MiB RAM detected (need ≥${SQLC_MIN_RAM_MIB}MiB for wazero go run).`, + ); + console.error( + "[migrate] goose already applied. Install a prebuilt sqlc binary, or run --sqlc on a larger host.", + ); + console.error( + "[migrate] Or set DESCRYBE_SQLC_MIN_RAM_MIB=0 to force (may OOM).", + ); + process.exit(1); +} + console.log("==> sqlc generate"); const sqlc = spawnSync("sqlc", ["generate"], { cwd: apiDir, @@ -54,13 +129,26 @@ const sqlc = spawnSync("sqlc", ["generate"], { stdio: "inherit", shell: process.platform === "win32", }); -if (sqlc.status !== 0) { - console.log("sqlc not on PATH (or failed); using go run"); - run("go", [ - "run", - "github.com/sqlc-dev/sqlc/cmd/sqlc@v1.28.0", - "generate", - ]); +if (sqlc.status === 0) { + console.log("==> done"); + process.exit(0); } +console.log("sqlc not on PATH (or failed); using go run"); +if (ram != null && ram < SQLC_MIN_RAM_MIB) { + console.error( + `[migrate] go run sqlc will likely OOM on ~${ram}MiB (wazero ~4GiB heap).`, + ); + console.error( + "[migrate] Install https://docs.sqlc.dev/en/latest/overview/install.html then retry, or use a larger host.", + ); + process.exit(1); +} + +run("go", [ + "run", + "github.com/sqlc-dev/sqlc/cmd/sqlc@v1.28.0", + "generate", +]); + console.log("==> done");