openvibers/openvibe.wiki Commits
The perf-budget test boots its server on its own PGlite directory (WIKI_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. The exit wait is registered at spawn and raced against 12 s, so a server that crashed before the checks fails the test instead of ending it as a pass, and its database is removed only after it has exited. Found by the estate-wide floating-promise sweep; reviewed independently (its blocker, the exit wait, fixed here). npm test 32/32 test files passed.
Changes
@@@ -22,7 +22,7 @@* and wiki_event_outbox (openvibe-sdk/events PostgreSQL outbox).** openDb(config) the serving handle: DATABASE_URL; in development without it, an embedded PGlite-- * database in data/pglite (one process, nothing to install)++ * database in data/pglite (WIKI_PGLITE_DIR overrides it; one process, nothing to install)* migrate(config, {serving}) apply migrations/ with the owner role (DATABASE_DIRECT_URL), then close it*/const fs = require('fs');@@@ -43,9 +43,10 @@ const DEV_PGLITE = path.join(__dirname, '..', 'data', 'pglite');function openDb(config, { registry, log = console } = {}) {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 wiki)');-- log.warn(`[Wiki] DATABASE_URL unset: embedded PGlite database in ${DEV_PGLITE} (development only, one process)`);-- fs.mkdirSync(DEV_PGLITE, { recursive: true });-- return createDb({ pglite: DEV_PGLITE, service: 'wiki', registry, log });++ const dir = process.env.WIKI_PGLITE_DIR || DEV_PGLITE;++ log.warn(`[Wiki] DATABASE_URL unset: embedded PGlite database in ${dir} (development only, one process)`);++ fs.mkdirSync(dir, { recursive: true });++ return createDb({ pglite: dir, service: 'wiki', registry, log });}return createDb({ url: config.db.url, service: 'wiki', registry, log });}@@@ -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,14 +26,24 @@ 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 fresh PGlite database of this run's own in a temp dir (server/db.js WIKI_PGLITE_DIR), never the shared++ // data/pglite the dev server uses. DATABASE_URL/DATABASE_DIRECT_URL are cleared too, so an inherited one++ // cannot point the child at a database other runs are using.++ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ov-wiki-budget-'));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',++ WIKI_PGLITE_DIR: path.join(dir, 'pglite'), DATABASE_URL: '', DATABASE_DIRECT_URL: '',++ },stdio: ['ignore', 'ignore', 'pipe'],});let stderr = '';child.stderr.on('data', (d) => { stderr = (stderr + d).slice(-2000); });++ // Registered at spawn: a server that already crashed has exited before the finally below, and waiting on++ // once('exit') then would never resolve (an unref'd timer does not hold the loop, so the test would end as a pass).++ const exited = new Promise((resolve) => { child.once('exit', resolve); child.once('error', resolve); });const base = `http://127.0.0.1:${port}`;try {let up = false;@@@ -47,5 +59,10 @@ const freePort = () => new Promise((resolve) => { const s = net.createServer();console.log('perf budget: all checks passed');} finally {child.kill();++ // The server bounds its own shutdown at 10 s; wait for the real exit before removing its database.++ let timer;++ await Promise.race([exited, new Promise((resolve) => { timer = setTimeout(resolve, 12000); })]);++ clearTimeout(timer);++ fs.rmSync(dir, { recursive: true, force: true });}})().catch((err) => { console.error(err); process.exitCode = 1; });
@@ -22,7 +22,7 @@
@@ -22,7 +22,7 @@
* and wiki_event_outbox (openvibe-sdk/events PostgreSQL outbox).
* and wiki_event_outbox (openvibe-sdk/events PostgreSQL outbox).
*
*
* openDb(config) the serving handle: DATABASE_URL; in development without it, an embedded PGlite
* openDb(config) the serving handle: DATABASE_URL; in development without it, an embedded PGlite
- * database in data/pglite (one process, nothing to install)
+ * database in data/pglite (WIKI_PGLITE_DIR overrides it; one process, nothing to install)
* migrate(config, {serving}) apply migrations/ with the owner role (DATABASE_DIRECT_URL), then close it
* migrate(config, {serving}) apply migrations/ with the owner role (DATABASE_DIRECT_URL), then close it
*/
*/
const fs = require('fs');
const fs = require('fs');
@@ -43,9 +43,10 @@ const DEV_PGLITE = path.join(__dirname, '..', 'data', 'pglite');
@@ -43,9 +43,10 @@ const DEV_PGLITE = path.join(__dirname, '..', 'data', 'pglite');
function openDb(config, { registry, log = console } = {}) {
function openDb(config, { registry, log = console } = {}) {
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 wiki)');
if (config.isProduction) throw new Error('DATABASE_URL is not set: production serves from PostgreSQL (OpenVibe.Host roles/data add-service.sh wiki)');
- log.warn(`[Wiki] DATABASE_URL unset: embedded PGlite database in ${DEV_PGLITE} (development only, one process)`);
- fs.mkdirSync(DEV_PGLITE, { recursive: true });
- return createDb({ pglite: DEV_PGLITE, service: 'wiki', registry, log });
+ const dir = process.env.WIKI_PGLITE_DIR || DEV_PGLITE;
+ log.warn(`[Wiki] DATABASE_URL unset: embedded PGlite database in ${dir} (development only, one process)`);
+ fs.mkdirSync(dir, { recursive: true });
+ return createDb({ pglite: dir, service: 'wiki', registry, log });
}
}
return createDb({ url: config.db.url, service: 'wiki', registry, log });
return createDb({ url: config.db.url, service: 'wiki', registry, log });
}
}
@@ -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,14 +26,24 @@ const BUDGETS = {
@@ -24,14 +26,24 @@ 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 fresh PGlite database of this run's own in a temp dir (server/db.js WIKI_PGLITE_DIR), never the shared
+ // data/pglite the dev server uses. DATABASE_URL/DATABASE_DIRECT_URL are cleared too, so an inherited one
+ // cannot point the child at a database other runs are using.
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ov-wiki-budget-'));
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',
+ WIKI_PGLITE_DIR: path.join(dir, 'pglite'), DATABASE_URL: '', DATABASE_DIRECT_URL: '',
+ },
stdio: ['ignore', 'ignore', 'pipe'],
stdio: ['ignore', 'ignore', 'pipe'],
});
});
let stderr = '';
let stderr = '';
child.stderr.on('data', (d) => { stderr = (stderr + d).slice(-2000); });
child.stderr.on('data', (d) => { stderr = (stderr + d).slice(-2000); });
+ // Registered at spawn: a server that already crashed has exited before the finally below, and waiting on
+ // once('exit') then would never resolve (an unref'd timer does not hold the loop, so the test would end as a pass).
+ const exited = new Promise((resolve) => { child.once('exit', resolve); child.once('error', resolve); });
const base = `http://127.0.0.1:${port}`;
const base = `http://127.0.0.1:${port}`;
try {
try {
let up = false;
let up = false;
@@ -47,5 +59,10 @@ const freePort = () => new Promise((resolve) => { const s = net.createServer();
@@ -47,5 +59,10 @@ 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();
+ // The server bounds its own shutdown at 10 s; wait for the real exit before removing its database.
+ let timer;
+ await Promise.race([exited, new Promise((resolve) => { timer = setTimeout(resolve, 12000); })]);
+ clearTimeout(timer);
+ fs.rmSync(dir, { recursive: true, force: true });
}
}
})().catch((err) => { console.error(err); process.exitCode = 1; });
})().catch((err) => { console.error(err); process.exitCode = 1; });