openvibers/openvibe.live Commits
Scripts open the database themselves (the Rundown backfill stopped at "the database is not open") (#645)
Changes
@@@ -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) {@@@ -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 NULLUNION SELECT stream_id, vod_id FROM rundown_segments WHERE vod_id IS NOT NULL) x ORDER BY stream_id`).all();@@@ -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) {nnew file mode 100644@@@ -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`);
@@ -13,6 +13,7 @@ const db = require('../server/db/database');
@@ -13,6 +13,7 @@ const db = require('../server/db/database');
const byo = require('../server/ai/byo-credentials');
const byo = require('../server/ai/byo-credentials');
(async () => {
(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();
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;
let moved = 0; let failed = 0;
for (const { user_id: userId } of rows) {
for (const { user_id: userId } of rows) {
@@ -18,6 +18,9 @@ const PACE_MS = 120;
@@ -18,6 +18,9 @@ const PACE_MS = 120;
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
(async () => {
(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 (
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
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();
UNION SELECT stream_id, vod_id FROM rundown_segments WHERE vod_id IS NOT NULL) x ORDER BY stream_id`).all();
@@ -13,6 +13,7 @@ const db = require('../server/db/database');
@@ -13,6 +13,7 @@ const db = require('../server/db/database');
const quota = require('../server/ai/viewer-quota');
const quota = require('../server/ai/viewer-quota');
(async () => {
(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();
const rows = await db.getDb().prepare('SELECT user_id FROM channel_ai_config ORDER BY user_id').all();
let failed = 0;
let failed = 0;
for (const { user_id: userId } of rows) {
for (const { user_id: userId } of rows) {
new file mode 100644
new file mode 100644
@@ -0,0 +1,27 @@
@@ -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`);