openvibers/openvibe.live Commits

Scripts open the database themselves (the Rundown backfill stopped at "the database is not open") (#645)

OP OpenVibers committed 6 days ago · d675172618 · 4 files, +32 −0

The service opens the database at boot; a script run on the host does not. rundown-vod-backfill.js, sync-viewer-quotas.js
and move-byo-keys-to-ai.js called db.getDb() first. They await db.initDb() now, and test/scripts-open-db.test.js
fails any script under scripts/ that queries before opening it (and fails if it finds none to check).

Changes

ddiff --git a/scripts/move-byo-keys-to-ai.js b/scripts/move-byo-keys-to-ai.js
iindex d21ffd80..3085c43f 100644
---- a/scripts/move-byo-keys-to-ai.js
++++ b/scripts/move-byo-keys-to-ai.js
@@@ -13,6 +13,7 @@ const db = require('../server/db/database');
const byo = require('../server/ai/byo-credentials');
(async () => {
++ await db.initDb(); // a script opens the database itself (the service does at boot)
const rows = await db.getDb().prepare("SELECT user_id FROM channel_ai_config WHERE byo_key IS NOT NULL AND TRIM(byo_key) != '' ORDER BY user_id").all();
let moved = 0; let failed = 0;
for (const { user_id: userId } of rows) {
ddiff --git a/scripts/rundown-vod-backfill.js b/scripts/rundown-vod-backfill.js
iindex 1150fd90..8bf90214 100644
---- a/scripts/rundown-vod-backfill.js
++++ b/scripts/rundown-vod-backfill.js
@@@ -18,6 +18,9 @@ const PACE_MS = 120;
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
(async () => {
++ // The database opens at boot in the service; a script has to open it itself (the first run, 2026-11-07, stopped
++ // at "the database is not open").
++ await db.initDb();
const rows = await db.getDb().prepare(`SELECT DISTINCT stream_id, vod_id FROM (
SELECT stream_id, vod_id FROM rundown_episodes WHERE vod_id IS NOT NULL
UNION SELECT stream_id, vod_id FROM rundown_segments WHERE vod_id IS NOT NULL) x ORDER BY stream_id`).all();
ddiff --git a/scripts/sync-viewer-quotas.js b/scripts/sync-viewer-quotas.js
iindex aadd42fc..c7fbbd9a 100644
---- a/scripts/sync-viewer-quotas.js
++++ b/scripts/sync-viewer-quotas.js
@@@ -13,6 +13,7 @@ const db = require('../server/db/database');
const quota = require('../server/ai/viewer-quota');
(async () => {
++ await db.initDb(); // a script opens the database itself (the service does at boot)
const rows = await db.getDb().prepare('SELECT user_id FROM channel_ai_config ORDER BY user_id').all();
let failed = 0;
for (const { user_id: userId } of rows) {
ddiff --git a/test/scripts-open-db.test.js b/test/scripts-open-db.test.js
nnew file mode 100644
iindex 00000000..d68726b2
---- /dev/null
++++ b/test/scripts-open-db.test.js
@@@ -0,0 +1,27 @@
++'use strict';
++/**
++ * Every operator script that reads the database opens it first. The service opens the database at boot; a script run
++ * on the host does not, and `db.getDb()` before `initDb()` stops with "the database is not open" (the Rundown VOD
++ * backfill's first run, 2026-11-07, after Live #634 deployed). This reads each script under scripts/ that requires
++ * server/db/database and uses it, and asks for an `initDb()` call before its first query.
++ */
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++
++const dir = path.join(__dirname, '..', 'scripts');
++const QUERY = /\bdb\.(getDb\(\)\.|get\(|all\(|run\(|prepare\()/;
++const offenders = [];
++let checked = 0;
++for (const name of fs.readdirSync(dir).filter((f) => f.endsWith('.js'))) {
++ const src = fs.readFileSync(path.join(dir, name), 'utf8');
++ if (!/require\(['"]\.\.\/server\/db\/database['"]\)/.test(src)) continue;
++ const q = src.search(QUERY);
++ if (q < 0) continue;
++ checked += 1;
++ const init = src.search(/\binitDb\s*\(/);
++ if (init < 0 || init > q) offenders.push(name);
++}
++assert.ok(checked >= 3, `the check found the scripts it guards (found ${checked})`);
++assert.deepStrictEqual(offenders, [], `scripts that query the database before opening it: ${offenders.join(', ')}`);
++console.log(`scripts open the database first: ${checked} checked`);