openvibers/openvibe.blog Commits
The perf-budget test boots its server on its own PGlite directory (BLOG_PGLITE_DIR, a temp dir removed afterwards) with DATABASE_URL cleared: it used to fall back to the shared dev database data/pglite and migrate it. It also asserts the isolated directory was used. Found by the estate-wide floating-promise sweep (test isolation lost in the PostgreSQL move); reviewed independently (VERDICT: SHIP). npm test 25/25 test files passed.
Changes
@@@ -19,7 +19,7 @@ TRUST_PROXY=2# PostgreSQL (ADR-035), written by OpenVibe.Host roles/data/add-service.sh blog: the runtime role through PgBouncer,# the owner on a direct connection (migrations), and Valkey (shared limit counters).--# Without DATABASE_URL, development uses an embedded PGlite database in data/pglite.++# Without DATABASE_URL, development uses an embedded PGlite database in data/pglite (BLOG_PGLITE_DIR overrides it).DATABASE_URL=DATABASE_DIRECT_URL=VALKEY_URL=@@@ -36,7 +36,9 @@ function load(env = process.env) {},// PostgreSQL (ADR-035): DATABASE_URL serves (PgBouncer), DATABASE_DIRECT_URL migrates (owner role).-- db: { url: env.DATABASE_URL || '', directUrl: env.DATABASE_DIRECT_URL || '' },++ // Non-production without DATABASE_URL: the embedded PGlite database in data/pglite++ // (BLOG_PGLITE_DIR, tests: an isolated directory of their own).++ db: { url: env.DATABASE_URL || '', directUrl: env.DATABASE_DIRECT_URL || '', pgliteDir: env.BLOG_PGLITE_DIR || '' },valkey: { url: env.VALKEY_URL || '', prefix: env.VALKEY_PREFIX || 'ov:blog:' },// OpenVibe.Network: SSO (OAuth2 authorization server), JWKS, client-credentials tokens.@@@ -43,14 +43,16 @@ const DEV_PGLITE = path.join(__dirname, '..', 'data', 'pglite');/*** The serving handle (ADR-035): DATABASE_URL through PgBouncer; in development without it, an embedded PGlite-- * database in data/pglite. Migrations run first, as the owner (DATABASE_DIRECT_URL), or on the embedded handle.++ * database in data/pglite (BLOG_PGLITE_DIR overrides the directory — how a test gets its own). Migrations run++ * first, as the owner (DATABASE_DIRECT_URL), or on the embedded handle.*/async function openDb(config, { log = console, registry } = {}) {if (!config.db.url) {if (config.isProduction) throw new Error('DATABASE_URL is not set: production serves from PostgreSQL (OpenVibe.Host roles/data add-service.sh blog)');-- log.warn(`[Blog] DATABASE_URL unset: embedded PGlite database in ${DEV_PGLITE} (development only, one process)`);-- fs.mkdirSync(DEV_PGLITE, { recursive: true });-- const db = createDb({ pglite: DEV_PGLITE, service: 'blog', registry, log });++ const dir = config.db.pgliteDir || DEV_PGLITE;++ log.warn(`[Blog] DATABASE_URL unset: embedded PGlite database in ${dir} (development only, one process)`);++ fs.mkdirSync(dir, { recursive: true });++ const db = createDb({ pglite: dir, service: 'blog', registry, log });await db.migrate({ dir: MIGRATIONS, log });return db;}@@@ -4,7 +4,9 @@// measurement; raising one is a decision to state in the commit.// node test/perf-budget.test.jsconst assert = require('assert');++const fs = require('fs');const net = require('net');++const os = require('os');const path = require('path');const { spawn } = require('child_process');const { measure, check, format } = require('openvibe-shared/perf-budget');@@@ -24,10 +26,17 @@ const BUDGETS = {const freePort = () => new Promise((resolve) => { const s = net.createServer(); s.listen(0, '127.0.0.1', () => { const { port } = s.address(); s.close(() => resolve(port)); }); });(async () => {++ // A database of its own (not the shared dev PGlite in data/pglite, and not whatever the caller's++ // DATABASE_URL names), so the measurement is the server on a fresh database and the run leaves nothing.++ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ov-budget-'));++ const pgliteDir = path.join(dir, 'pglite');const port = await freePort();const child = spawn(process.execPath, [path.join(__dirname, '..', 'server', 'index.js')], {cwd: path.join(__dirname, '..'),-- env: { ...process.env, PORT: String(port), HOST: '127.0.0.1', NODE_ENV: 'test' },++ env: {++ ...process.env, PORT: String(port), HOST: '127.0.0.1', NODE_ENV: 'test',++ DATABASE_URL: '', DATABASE_DIRECT_URL: '', VALKEY_URL: '', BLOG_PGLITE_DIR: pgliteDir,++ },stdio: ['ignore', 'ignore', 'pipe'],});let stderr = '';@@@ -40,6 +49,7 @@ const freePort = () => new Promise((resolve) => { const s = net.createServer();if (!up) await new Promise((r) => setTimeout(r, 100));}assert.ok(up, `the server did not start:\n${stderr}`);++ assert.ok(fs.existsSync(pgliteDir), 'the server did not use the isolated database (BLOG_PGLITE_DIR)');const m = await measure({ base });const over = check(m, BUDGETS);assert.deepStrictEqual(over, [], format(m, over));@@@ -47,5 +57,6 @@ const freePort = () => new Promise((resolve) => { const s = net.createServer();console.log('perf budget: all checks passed');} finally {child.kill();++ fs.rmSync(dir, { recursive: true, force: true });}})().catch((err) => { console.error(err); process.exitCode = 1; });
@@ -19,7 +19,7 @@ TRUST_PROXY=2
@@ -19,7 +19,7 @@ TRUST_PROXY=2
# PostgreSQL (ADR-035), written by OpenVibe.Host roles/data/add-service.sh blog: the runtime role through PgBouncer,
# PostgreSQL (ADR-035), written by OpenVibe.Host roles/data/add-service.sh blog: the runtime role through PgBouncer,
# the owner on a direct connection (migrations), and Valkey (shared limit counters).
# the owner on a direct connection (migrations), and Valkey (shared limit counters).
-# Without DATABASE_URL, development uses an embedded PGlite database in data/pglite.
+# Without DATABASE_URL, development uses an embedded PGlite database in data/pglite (BLOG_PGLITE_DIR overrides it).
DATABASE_URL=
DATABASE_URL=
DATABASE_DIRECT_URL=
DATABASE_DIRECT_URL=
VALKEY_URL=
VALKEY_URL=
@@ -36,7 +36,9 @@ function load(env = process.env) {
@@ -36,7 +36,9 @@ function load(env = process.env) {
},
},
// PostgreSQL (ADR-035): DATABASE_URL serves (PgBouncer), DATABASE_DIRECT_URL migrates (owner role).
// PostgreSQL (ADR-035): DATABASE_URL serves (PgBouncer), DATABASE_DIRECT_URL migrates (owner role).
- db: { url: env.DATABASE_URL || '', directUrl: env.DATABASE_DIRECT_URL || '' },
+ // Non-production without DATABASE_URL: the embedded PGlite database in data/pglite
+ // (BLOG_PGLITE_DIR, tests: an isolated directory of their own).
+ db: { url: env.DATABASE_URL || '', directUrl: env.DATABASE_DIRECT_URL || '', pgliteDir: env.BLOG_PGLITE_DIR || '' },
valkey: { url: env.VALKEY_URL || '', prefix: env.VALKEY_PREFIX || 'ov:blog:' },
valkey: { url: env.VALKEY_URL || '', prefix: env.VALKEY_PREFIX || 'ov:blog:' },
// OpenVibe.Network: SSO (OAuth2 authorization server), JWKS, client-credentials tokens.
// OpenVibe.Network: SSO (OAuth2 authorization server), JWKS, client-credentials tokens.
@@ -43,14 +43,16 @@ const DEV_PGLITE = path.join(__dirname, '..', 'data', 'pglite');
@@ -43,14 +43,16 @@ const DEV_PGLITE = path.join(__dirname, '..', 'data', 'pglite');
/**
/**
* The serving handle (ADR-035): DATABASE_URL through PgBouncer; in development without it, an embedded PGlite
* The serving handle (ADR-035): DATABASE_URL through PgBouncer; in development without it, an embedded PGlite
- * database in data/pglite. Migrations run first, as the owner (DATABASE_DIRECT_URL), or on the embedded handle.
+ * database in data/pglite (BLOG_PGLITE_DIR overrides the directory — how a test gets its own). Migrations run
+ * first, as the owner (DATABASE_DIRECT_URL), or on the embedded handle.
*/
*/
async function openDb(config, { log = console, registry } = {}) {
async function openDb(config, { log = console, registry } = {}) {
if (!config.db.url) {
if (!config.db.url) {
if (config.isProduction) throw new Error('DATABASE_URL is not set: production serves from PostgreSQL (OpenVibe.Host roles/data add-service.sh blog)');
if (config.isProduction) throw new Error('DATABASE_URL is not set: production serves from PostgreSQL (OpenVibe.Host roles/data add-service.sh blog)');
- log.warn(`[Blog] DATABASE_URL unset: embedded PGlite database in ${DEV_PGLITE} (development only, one process)`);
- fs.mkdirSync(DEV_PGLITE, { recursive: true });
- const db = createDb({ pglite: DEV_PGLITE, service: 'blog', registry, log });
+ const dir = config.db.pgliteDir || DEV_PGLITE;
+ log.warn(`[Blog] DATABASE_URL unset: embedded PGlite database in ${dir} (development only, one process)`);
+ fs.mkdirSync(dir, { recursive: true });
+ const db = createDb({ pglite: dir, service: 'blog', registry, log });
await db.migrate({ dir: MIGRATIONS, log });
await db.migrate({ dir: MIGRATIONS, log });
return db;
return db;
}
}
@@ -4,7 +4,9 @@
@@ -4,7 +4,9 @@
// measurement; raising one is a decision to state in the commit.
// measurement; raising one is a decision to state in the commit.
// node test/perf-budget.test.js
// node test/perf-budget.test.js
const assert = require('assert');
const assert = require('assert');
+const fs = require('fs');
const net = require('net');
const net = require('net');
+const os = require('os');
const path = require('path');
const path = require('path');
const { spawn } = require('child_process');
const { spawn } = require('child_process');
const { measure, check, format } = require('openvibe-shared/perf-budget');
const { measure, check, format } = require('openvibe-shared/perf-budget');
@@ -24,10 +26,17 @@ const BUDGETS = {
@@ -24,10 +26,17 @@ const BUDGETS = {
const freePort = () => new Promise((resolve) => { const s = net.createServer(); s.listen(0, '127.0.0.1', () => { const { port } = s.address(); s.close(() => resolve(port)); }); });
const freePort = () => new Promise((resolve) => { const s = net.createServer(); s.listen(0, '127.0.0.1', () => { const { port } = s.address(); s.close(() => resolve(port)); }); });
(async () => {
(async () => {
+ // A database of its own (not the shared dev PGlite in data/pglite, and not whatever the caller's
+ // DATABASE_URL names), so the measurement is the server on a fresh database and the run leaves nothing.
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ov-budget-'));
+ const pgliteDir = path.join(dir, 'pglite');
const port = await freePort();
const port = await freePort();
const child = spawn(process.execPath, [path.join(__dirname, '..', 'server', 'index.js')], {
const child = spawn(process.execPath, [path.join(__dirname, '..', 'server', 'index.js')], {
cwd: path.join(__dirname, '..'),
cwd: path.join(__dirname, '..'),
- env: { ...process.env, PORT: String(port), HOST: '127.0.0.1', NODE_ENV: 'test' },
+ env: {
+ ...process.env, PORT: String(port), HOST: '127.0.0.1', NODE_ENV: 'test',
+ DATABASE_URL: '', DATABASE_DIRECT_URL: '', VALKEY_URL: '', BLOG_PGLITE_DIR: pgliteDir,
+ },
stdio: ['ignore', 'ignore', 'pipe'],
stdio: ['ignore', 'ignore', 'pipe'],
});
});
let stderr = '';
let stderr = '';
@@ -40,6 +49,7 @@ const freePort = () => new Promise((resolve) => { const s = net.createServer();
@@ -40,6 +49,7 @@ const freePort = () => new Promise((resolve) => { const s = net.createServer();
if (!up) await new Promise((r) => setTimeout(r, 100));
if (!up) await new Promise((r) => setTimeout(r, 100));
}
}
assert.ok(up, `the server did not start:\n${stderr}`);
assert.ok(up, `the server did not start:\n${stderr}`);
+ assert.ok(fs.existsSync(pgliteDir), 'the server did not use the isolated database (BLOG_PGLITE_DIR)');
const m = await measure({ base });
const m = await measure({ base });
const over = check(m, BUDGETS);
const over = check(m, BUDGETS);
assert.deepStrictEqual(over, [], format(m, over));
assert.deepStrictEqual(over, [], format(m, over));
@@ -47,5 +57,6 @@ const freePort = () => new Promise((resolve) => { const s = net.createServer();
@@ -47,5 +57,6 @@ const freePort = () => new Promise((resolve) => { const s = net.createServer();
console.log('perf budget: all checks passed');
console.log('perf budget: all checks passed');
} finally {
} finally {
child.kill();
child.kill();
+ fs.rmSync(dir, { recursive: true, force: true });
}
}
})().catch((err) => { console.error(err); process.exitCode = 1; });
})().catch((err) => { console.error(err); process.exitCode = 1; });