feat(dashboard-agent-db): run migrations over a direct (non-pooler) connection (#4054)
## Summary The in-dashboard agent's datastore now runs migrations over a direct (non-pooler) connection. A transaction-mode pooler can't run the migrator (no advisory locks, no multi-statement DDL), so when the agent's database sits behind a pooler the migration step needs a separate direct connection. The application keeps connecting over the pooled `DASHBOARD_AGENT_DATABASE_URL`. Only the migration entry points changed (`drizzle.config.ts`, `migrate.mjs`, `migrate-status.mjs`); the runtime client is untouched. ## Connection resolution (migrations) ``` DASHBOARD_AGENT_DIRECT_URL direct agent connection (used for migrations) DASHBOARD_AGENT_DATABASE_URL pooled agent connection (preserves current behavior) DIRECT_URL main direct connection (single-database fallback) DATABASE_URL last resort ``` Mirrors the existing `DATABASE_URL` / `DIRECT_URL` split. Fully backward-compatible: with nothing new set, resolution is identical to before. The agent-specific vars take precedence over the main `DIRECT_URL`, so a separate agent database is never migrated against the wrong one. When the agent falls back to the main single database, migrations now prefer its direct connection.
This commit is contained in:
@@ -4,10 +4,13 @@ The conversation datastore for the in-dashboard agent, isolated from the main
|
||||
Prisma database. Drizzle (postgres-js) over a dedicated `trigger_dashboard_agent`
|
||||
Postgres schema.
|
||||
|
||||
- **Cloud:** a separate PlanetScale Postgres database (`DASHBOARD_AGENT_DATABASE_URL`),
|
||||
reached over a standard pooled connection.
|
||||
- **OSS / self-host:** falls back to the main `DATABASE_URL`; the tables live in
|
||||
the dedicated `trigger_dashboard_agent` schema, isolated from Prisma's `public`.
|
||||
- **Cloud:** a separate PlanetScale Postgres database. The app connects over a
|
||||
pooled connection (`DASHBOARD_AGENT_DATABASE_URL`); migrations run over a direct
|
||||
(non-pooler) connection (`DASHBOARD_AGENT_DIRECT_URL`), since a transaction-mode
|
||||
pooler can't run the migrator.
|
||||
- **OSS / self-host:** falls back to the main `DATABASE_URL` (and `DIRECT_URL` for
|
||||
migrations); the tables live in the dedicated `trigger_dashboard_agent` schema,
|
||||
isolated from Prisma's `public`.
|
||||
|
||||
The schema is **foreign-key-free** — it references main entities (`organizationId`,
|
||||
`userId`) by id only, because in cloud it lives in a different database.
|
||||
@@ -36,7 +39,7 @@ of truth.
|
||||
|
||||
```bash
|
||||
pnpm run db:generate # generate SQL migration from src/schema.ts (offline)
|
||||
pnpm run db:migrate # apply migrations (needs DASHBOARD_AGENT_DATABASE_URL or DATABASE_URL)
|
||||
pnpm run db:migrate # apply migrations (direct url: DASHBOARD_AGENT_DIRECT_URL, falling back to DASHBOARD_AGENT_DATABASE_URL / DIRECT_URL / DATABASE_URL)
|
||||
```
|
||||
|
||||
drizzle-kit is scoped to the `trigger_dashboard_agent` schema (`schemaFilter`), so
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
|
||||
// Cloud points at the dedicated PlanetScale database; OSS falls back to the main
|
||||
// DATABASE_URL (tables still land in the trigger_dashboard_agent schema).
|
||||
// Migrations need a direct (non-pooler) connection; a transaction-mode pooler
|
||||
// can't run the migrator. Prefer the agent's direct url, then its pooled url,
|
||||
// then the main DIRECT_URL/DATABASE_URL (OSS single-database fallback; tables
|
||||
// still land in the trigger_dashboard_agent schema).
|
||||
const url =
|
||||
process.env.DASHBOARD_AGENT_DIRECT_URL ??
|
||||
process.env.DASHBOARD_AGENT_DATABASE_URL ??
|
||||
process.env.DIRECT_URL ??
|
||||
process.env.DATABASE_URL ??
|
||||
"postgres://placeholder"; // generate is offline; a real url is only needed for migrate/studio
|
||||
|
||||
|
||||
@@ -8,11 +8,16 @@ import postgres from "postgres";
|
||||
const MIGRATIONS_SCHEMA = "drizzle";
|
||||
const MIGRATIONS_TABLE = "__dashboard_agent_migrations";
|
||||
|
||||
const connectionString = process.env.DASHBOARD_AGENT_DATABASE_URL ?? process.env.DATABASE_URL;
|
||||
// Match migrate.mjs: a direct (non-pooler) connection, same precedence.
|
||||
const connectionString =
|
||||
process.env.DASHBOARD_AGENT_DIRECT_URL ??
|
||||
process.env.DASHBOARD_AGENT_DATABASE_URL ??
|
||||
process.env.DIRECT_URL ??
|
||||
process.env.DATABASE_URL;
|
||||
|
||||
if (!connectionString) {
|
||||
console.error(
|
||||
"[dashboard-agent-db] DASHBOARD_AGENT_DATABASE_URL / DATABASE_URL not set; cannot check status."
|
||||
"[dashboard-agent-db] No database url set (DASHBOARD_AGENT_DIRECT_URL / DASHBOARD_AGENT_DATABASE_URL / DIRECT_URL / DATABASE_URL); cannot check status."
|
||||
);
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,19 @@ import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import { migrate } from "drizzle-orm/postgres-js/migrator";
|
||||
import postgres from "postgres";
|
||||
|
||||
// Cloud points at the dedicated dashboard-agent database; OSS falls back to the
|
||||
// main DATABASE_URL (tables still land in the `trigger_dashboard_agent` schema).
|
||||
const connectionString = process.env.DASHBOARD_AGENT_DATABASE_URL ?? process.env.DATABASE_URL;
|
||||
// Migrations need a direct (non-pooler) connection; a transaction-mode pooler
|
||||
// can't run the migrator. Prefer the agent's direct url, then its pooled url,
|
||||
// then the main DIRECT_URL/DATABASE_URL (OSS single-database fallback; tables
|
||||
// still land in the `trigger_dashboard_agent` schema).
|
||||
const connectionString =
|
||||
process.env.DASHBOARD_AGENT_DIRECT_URL ??
|
||||
process.env.DASHBOARD_AGENT_DATABASE_URL ??
|
||||
process.env.DIRECT_URL ??
|
||||
process.env.DATABASE_URL;
|
||||
|
||||
if (!connectionString) {
|
||||
console.error(
|
||||
"[dashboard-agent-db] DASHBOARD_AGENT_DATABASE_URL / DATABASE_URL not set; cannot migrate."
|
||||
"[dashboard-agent-db] No database url set (DASHBOARD_AGENT_DIRECT_URL / DASHBOARD_AGENT_DATABASE_URL / DIRECT_URL / DATABASE_URL); cannot migrate."
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user