mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-01 06:42:06 +01:00
Allow owned loopback Postgres databases in recovery qualification
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
16df54ba90
commit
14d60e1e4f
6 files changed
+135
-8
No files matched your search
@@ -0,0 +1,47 @@
|
||||
/** Launcher-owned disposable database. The admin credential never enters the
|
||||
* server/browser environment. Unknown remote cleanup keeps this database alive. */
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
||||
import { createDb } from "../../packages/db/src/index.js";
|
||||
import { paperclipConfigSchema } from "../../packages/shared/src/config-schema.js";
|
||||
import { recordControllerDatabaseOwnership } from "./instance-isolation.js";
|
||||
import { prepareRunnerE2EServerConfig } from "./server-config.js";
|
||||
|
||||
export async function createExternalControllerDatabase(input: {
|
||||
adminUrl: string; temporaryRoot: string; configPath: string; serverPort: number;
|
||||
}) {
|
||||
const url = new URL(input.adminUrl);
|
||||
if (!["postgres:", "postgresql:"].includes(url.protocol)
|
||||
|| !["127.0.0.1", "localhost", "[::1]"].includes(url.hostname)) {
|
||||
throw new Error("E2E Postgres administrator must use an explicit loopback test server");
|
||||
}
|
||||
await (await prepareRunnerE2EServerConfig(input))?.close();
|
||||
const config = paperclipConfigSchema.parse(JSON.parse(await readFile(input.configPath, "utf8")));
|
||||
if (config.database.mode !== "embedded-postgres") throw new Error("E2E database fixture already configured");
|
||||
const databaseName = `runner_e2e_${randomUUID().replaceAll("-", "")}`;
|
||||
const admin = createDb(input.adminUrl, { maxConnections: 1 });
|
||||
let created = false;
|
||||
const cleanup = async () => {
|
||||
if (!created) return;
|
||||
const connection = createDb(input.adminUrl, { maxConnections: 1 });
|
||||
try {
|
||||
// No FORCE: a remaining controller keeps its evidence and fails cleanup.
|
||||
await connection.$client.unsafe(`drop database "${databaseName}"`);
|
||||
created = false;
|
||||
} finally { await connection.$client.end({ timeout: 1 }); }
|
||||
};
|
||||
try {
|
||||
await admin.$client.unsafe(`create database "${databaseName}"`);
|
||||
created = true;
|
||||
url.pathname = `/${databaseName}`;
|
||||
config.database = { ...config.database, mode: "postgres", connectionString: url.toString() };
|
||||
await mkdir(config.database.embeddedPostgresDataDir, { recursive: true, mode: 0o700 });
|
||||
await recordControllerDatabaseOwnership({ ...input, dataDirectory: config.database.embeddedPostgresDataDir,
|
||||
connectionString: url.toString(), externalDatabaseName: databaseName });
|
||||
await writeFile(input.configPath, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });
|
||||
return { cleanup };
|
||||
} catch (error) {
|
||||
await cleanup();
|
||||
throw error;
|
||||
} finally { await admin.$client.end({ timeout: 1 }); }
|
||||
}
|
||||
Reference in new issue
Block a user