diff --git a/src/db/ensure-runtime-schema.ts b/src/db/ensure-runtime-schema.ts new file mode 100644 index 0000000..55f8ad8 --- /dev/null +++ b/src/db/ensure-runtime-schema.ts @@ -0,0 +1,14 @@ +import { db } from "./client.js"; +import { log } from "../log.js"; + +async function ensureGrowConversationsMetadataColumn() { + await db.execute(` + ALTER TABLE grow_conversations + ADD COLUMN IF NOT EXISTS metadata jsonb NOT NULL DEFAULT '{}'::jsonb + `); +} + +export async function ensureRuntimeSchema() { + await ensureGrowConversationsMetadataColumn(); + log.info("runtime schema ensured"); +} diff --git a/src/index.ts b/src/index.ts index 73ba222..61057a3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,12 +24,14 @@ import { logRoutes } from "./routes/logs.js"; import { v1Routes } from "./v1/index.js"; import { startGrowEventsRedisConsumer } from "./events/redis-consumer.js"; import { db } from "./db/client.js"; +import { ensureRuntimeSchema } from "./db/ensure-runtime-schema.js"; import { hydratePortAllocator, reconcileOnBoot, ensureCentralGiteaReady } from "./docker/manager.js"; import { initCatalog } from "./agents/catalog.js"; async function main() { // Boot-time DB sanity + reconcile + central Gitea readiness. await db.execute("select 1"); + await ensureRuntimeSchema(); await hydratePortAllocator(); // Ensure central Gitea is reachable before accepting traffic (changes.md ยง2A). diff --git a/src/routes/users.ts b/src/routes/users.ts index 56747a4..335b6cc 100644 --- a/src/routes/users.ts +++ b/src/routes/users.ts @@ -3,7 +3,6 @@ import { requireUser, type AuthContext } from "../auth/clerk.js"; import { db } from "../db/client.js"; import { growEvents, users, userStacks, type UserStack } from "../db/schema.js"; import { and, desc, eq, inArray } from "drizzle-orm"; -import { provisionUserStack } from "../docker/manager.js"; import { log } from "../log.js"; import { config } from "../config.js"; import { ensureOnboardingBaselineQscore } from "../events/onboarding-qscore.js"; @@ -18,12 +17,6 @@ function publicStack(stack: UserStack | null | undefined) { return safe; } -function shouldStartProvisioning(stack: UserStack | null | undefined) { - if (!stack || stack.status === "error" || stack.status === "stopped") return true; - if (stack.status !== "provisioning") return false; - return Date.now() - stack.updatedAt.getTime() >= 5 * 60_000; -} - function userServiceTarget(path: string, search = "") { return new URL(`/api/v1/users${path}${search}`, config.userServiceUrl.replace(/\/$/, "")); } @@ -110,12 +103,6 @@ export function userRoutes() { where: eq(userStacks.userId, userId), }); - if (shouldStartProvisioning(stack)) { - void provisionUserStack(userId).catch((err) => - log.error({ err, userId }, "background provision failed"), - ); - } - return c.json({ user: userServiceUser, backendUser: userRow,