openvibers/openvibe.media Commits

N-1 fixtures re-recorded from 1157a54, the release now in production (npm run n-1:record).

OP OpenVibers committed 27 Sept 2026 · 743c86ff41 · 2 files, +34 −14


Changes

ddiff --git a/test/fixtures/n-1/client.json b/test/fixtures/n-1/client.json
iindex 2ff40cb..a987549 100644
---- a/test/fixtures/n-1/client.json
++++ b/test/fixtures/n-1/client.json
@@@ -1,13 +1,13 @@
{
"service": "media",
-- "release": "b7fbe65029f38fd3ec6b10919eab9b8ba13df9d4",
-- "recorded_at": "2026-09-26T14:14:01.055Z",
++ "release": "1157a5459a908ba5601a6321761e2954bdf94ff5",
++ "recorded_at": "2026-09-27T19:08:02.347Z",
"note": "N-1 fixture: written by `npm run n-1:record`, replayed by test/n-1.test.js",
"manifest": {
"service": "media",
-- "release": "b7fbe65029f3",
-- "released_at": "2026-09-26T13:16:26.000Z",
-- "booted_at": "2026-09-26T14:14:00.188Z",
++ "release": "1157a5459a90",
++ "released_at": "2026-09-26T16:56:08.000Z",
++ "booted_at": "2026-09-27T19:08:01.448Z",
"contracts_version": "0.54.0",
"packages": {
"openvibe-shared": "1.22.0",
@@@ -18,11 +18,11 @@
"components": {
"shell": {
"kind": "script",
-- "version": "b7fbe65029f3"
++ "version": "1157a5459a90"
},
"server": {
"kind": "server",
-- "version": "b7fbe65029f3"
++ "version": "1157a5459a90"
}
},
"assets": {},
@@@ -241,9 +241,7 @@
"objects[].metadata": "object",
"objects[].metadata.title": "string",
"objects[].metadata.duration_seconds": "number",
-- "objects[].metadata.health_status": "string",
-- "objects[].metadata.managed_stream_id": "null",
-- "objects[].metadata.recording": "boolean",
++ "objects[].metadata.auto_generated": "boolean",
"objects[].held": "boolean",
"objects[].readiness": "object",
"objects[].readiness.metadata": "boolean",
@@@ -254,8 +252,10 @@
"objects[].created_at": "string",
"objects[].updated_at": "string",
"objects[].deleted_at": "null",
-- "objects[].metadata.auto_generated": "boolean",
"objects[].metadata.filename": "string",
++ "objects[].metadata.health_status": "string",
++ "objects[].metadata.managed_stream_id": "null",
++ "objects[].metadata.recording": "boolean",
"next_cursor": "null",
"limit": "number"
},
ddiff --git a/test/fixtures/n-1/worker.json b/test/fixtures/n-1/worker.json
iindex a96c0a0..579f77c 100644
---- a/test/fixtures/n-1/worker.json
++++ b/test/fixtures/n-1/worker.json
@@@ -1,7 +1,7 @@
{
"service": "media",
-- "release": "b7fbe65029f38fd3ec6b10919eab9b8ba13df9d4",
-- "recorded_at": "2026-09-26T14:14:01.055Z",
++ "release": "1157a5459a908ba5601a6321761e2954bdf94ff5",
++ "recorded_at": "2026-09-27T19:08:02.347Z",
"note": "N-1 fixture: written by `npm run n-1:record`, replayed by test/n-1.test.js",
"user_version": 0,
"schema": [
@@@ -17,6 +17,10 @@
"CREATE TABLE media_locations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n object_id TEXT NOT NULL,\n provider TEXT NOT NULL CHECK(provider IN ('local', 'b2', 'r2')),\n bucket TEXT,\n key TEXT NOT NULL, -- absolute path for local, object key for b2/r2\n storage_class TEXT, -- hot (local) | cold (b2 canonical) | cache (r2)\n state TEXT NOT NULL DEFAULT 'pending' CHECK(state IN ('present', 'missing', 'pending', 'corrupt')),\n checksum TEXT,\n size_bytes INTEGER,\n verified_at DATETIME,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n UNIQUE(object_id, provider)\n)",
"CREATE TABLE media_namespaces (\n namespace TEXT PRIMARY KEY,\n app_id TEXT NOT NULL, -- the tenant it belongs to (and whose quota it counts against)\n parent TEXT, -- NULL for a root\n owner TEXT NOT NULL, -- service:<app_id> (a first-party tenant) | project:<prj_…> (a developer project)\n policy TEXT NOT NULL DEFAULT '{}', -- JSON: kinds, visibilities, max_object_bytes, strict_verbs (children inherit)\n quota_bytes INTEGER,\n quota_objects INTEGER,\n used_bytes INTEGER NOT NULL DEFAULT 0,\n used_objects INTEGER NOT NULL DEFAULT 0,\n reserved_bytes INTEGER NOT NULL DEFAULT 0,\n reserved_objects INTEGER NOT NULL DEFAULT 0,\n reconciled_at DATETIME,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP\n)",
"CREATE TABLE media_object_changes (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n object_id TEXT NOT NULL,\n change TEXT NOT NULL CHECK(change IN ('deleted', 'visibility_changed')),\n previous_visibility TEXT,\n visibility TEXT,\n changed_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n)",
++ "CREATE TABLE media_object_tier_decisions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n decided_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),\n object_id TEXT NOT NULL,\n app_id TEXT,\n action TEXT NOT NULL CHECK(action IN ('promote', 'demote')),\n from_provider TEXT,\n to_provider TEXT,\n outcome TEXT NOT NULL CHECK(outcome IN ('done', 'already', 'refused', 'failed', 'dry_run')),\n trigger TEXT NOT NULL, -- sweep | manual\n reason TEXT NOT NULL,\n inputs TEXT NOT NULL DEFAULT '{}', -- JSON: unique_viewers_7d, last_viewed_day, size, kind, lifecycle, canonical copy, held, R2 copy, gate\n thresholds TEXT NOT NULL DEFAULT '{}',-- JSON: the media.object_tier policy in force, each value with its source (default | setting)\n error TEXT\n)",
++ "CREATE TABLE media_object_view_salts (\n day TEXT PRIMARY KEY, -- YYYY-MM-DD (UTC)\n salt TEXT NOT NULL, -- 32 random bytes, hex; deleted with the day's hashes\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n)",
++ "CREATE TABLE media_object_viewer_days (\n day TEXT NOT NULL,\n object_id TEXT NOT NULL,\n viewer TEXT NOT NULL, -- 16 hex chars of HMAC-SHA256(salt of the day, client network)\n PRIMARY KEY (day, object_id, viewer)\n) WITHOUT ROWID",
++ "CREATE TABLE media_object_views_daily (\n object_id TEXT NOT NULL,\n day TEXT NOT NULL, -- YYYY-MM-DD (UTC)\n unique_viewers INTEGER NOT NULL DEFAULT 0,\n last_viewed_at TEXT, -- ISO 8601: the day's last new viewer\n PRIMARY KEY (object_id, day)\n)",
"CREATE TABLE media_objects (\n id TEXT PRIMARY KEY, -- med_<ULID> (time-sortable)\n app_id TEXT NOT NULL, -- tenant\n namespace TEXT NOT NULL, -- a media_namespaces row: the tenant's root (app id, or app.<project_id>[.sandbox]) or a child of it\n kind TEXT NOT NULL CHECK(kind IN ('vod', 'clip', 'file', 'thumbnail', 'screenshot', 'avatar', 'asset')),\n owner_subject TEXT, -- canonical subject (usr_<ULID>) when known\n owner_app TEXT, -- legacy owner: the app whose user-id space owner_user_id is in\n owner_user_id INTEGER,\n visibility TEXT NOT NULL DEFAULT 'private' CHECK(visibility IN ('public', 'unlisted', 'private')),\n lifecycle_status TEXT NOT NULL DEFAULT 'uploading' CHECK(lifecycle_status IN ('uploading', 'ready', 'failed', 'archived', 'deleted')),\n mime_type TEXT,\n size_bytes INTEGER NOT NULL DEFAULT 0,\n content_hash TEXT, -- sha256 hex\n canonical_provider TEXT, -- local | b2 | r2\n canonical_key TEXT,\n legacy_ref TEXT UNIQUE, -- legacy:<app>:<kind>:<id> for projected rows; NULL = native v2 object\n metadata TEXT NOT NULL DEFAULT '{}',\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n deleted_at DATETIME\n)",
"CREATE TABLE media_quota_reservations (\n object_id TEXT PRIMARY KEY,\n app_id TEXT NOT NULL,\n namespace TEXT NOT NULL,\n bytes INTEGER NOT NULL DEFAULT 0,\n expires_at DATETIME NOT NULL, -- the expiry sweep fails the upload after this (unless a multipart session is open)\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP\n)",
"CREATE TABLE media_relationships (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n from_object_id TEXT NOT NULL,\n relation TEXT NOT NULL, -- clip_of | thumbnail_of | derived_from | screenshot_of\n to_object_id TEXT NOT NULL,\n metadata TEXT NOT NULL DEFAULT '{}',\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n UNIQUE(from_object_id, relation, to_object_id)\n)",
@@@ -47,6 +51,9 @@
"CREATE INDEX idx_media_jobs_object ON media_jobs(object_id, job_type, status)",
"CREATE INDEX idx_media_jobs_status ON media_jobs(status, job_type)",
"CREATE INDEX idx_media_namespaces_app ON media_namespaces(app_id, namespace)",
++ "CREATE INDEX idx_media_object_tier_decisions_app ON media_object_tier_decisions(app_id, id)",
++ "CREATE INDEX idx_media_object_tier_decisions_object ON media_object_tier_decisions(object_id, id)",
++ "CREATE INDEX idx_media_object_views_daily_day ON media_object_views_daily(day, object_id)",
"CREATE INDEX idx_media_objects_app ON media_objects(app_id, id)",
"CREATE INDEX idx_media_objects_kind ON media_objects(app_id, kind)",
"CREATE INDEX idx_media_objects_lifecycle ON media_objects(lifecycle_status)",
@@@ -94,8 +101,12 @@
"DELETE FROM content_visits WHERE last_at < datetime('now', ?)",
"DELETE FROM files WHERE key = ?",
"DELETE FROM media_locations WHERE id = ?",
++ "DELETE FROM media_locations WHERE object_id = ? AND provider = 'r2'",
"DELETE FROM media_object_changes",
"DELETE FROM media_object_changes WHERE id = ?",
++ "DELETE FROM media_object_view_salts WHERE day < ?",
++ "DELETE FROM media_object_viewer_days WHERE day < ?",
++ "DELETE FROM media_object_views_daily WHERE day < ?",
"DELETE FROM media_objects WHERE id = ?",
"DELETE FROM media_quota_reservations WHERE object_id = ?",
"DELETE FROM media_settings WHERE key = ?",
@@@ -111,6 +122,8 @@
"INSERT INTO media_holds (object_id, kind, reason, created_by, note) VALUES (?, ?, ?, ?, ?)",
"INSERT INTO media_invariant_violations (object_id, level, size_bytes, threshold_bytes) VALUES (?, ?, ?, ?)",
"INSERT INTO media_locations (object_id, provider, bucket, key, storage_class, state, checksum, size_bytes, verified_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
++ "INSERT INTO media_object_tier_decisions (object_id, app_id, action, from_provider, to_provider, outcome, trigger, reason, inputs, thresholds, error) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
++ "INSERT INTO media_object_views_daily (object_id, day, unique_viewers, last_viewed_at) VALUES (?, ?, 1, ?) ON CONFLICT(object_id, day) DO UPDATE SET unique_viewers = unique_viewers + 1, last_viewed_at = excluded.last_viewed_at",
"INSERT INTO media_objects (id, app_id, namespace, kind, owner_subject, owner_app, owner_user_id, visibility, lifecycle_status, mime_type, size_bytes, content_hash, canonical_provider, canonical_key, legacy_ref, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, 'private', 'ready', ?, ?, ?, 'local', ?, NULL, ?)",
"INSERT INTO media_objects (id, app_id, namespace, kind, owner_subject, owner_app, owner_user_id, visibility, lifecycle_status, mime_type, size_bytes, content_hash, canonical_provider, canonical_key, legacy_ref, metadata, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, COALESCE(?, CURRENT_TIMESTAMP))",
"INSERT INTO media_quota_reservations (object_id, app_id, namespace, bytes, expires_at) VALUES (?, ?, ?, ?, ?) ON CONFLICT(object_id) DO UPDATE SET bytes = excluded.bytes, namespace = excluded.namespace, expires_at = MAX(expires_at, excluded.expires_at), updated_at = CURRENT_TIMESTAMP",
@@@ -133,6 +146,8 @@
"INSERT OR IGNORE INTO content_visits (content_type, content_id, visitor, first_at, last_at, visits) VALUES (?, ?, ?, ?, ?, 1)",
"INSERT OR IGNORE INTO media_namespaces (namespace, app_id, parent, owner) VALUES (?, ?, ?, ?)",
"INSERT OR IGNORE INTO media_namespaces (namespace, app_id, parent, owner) VALUES (?, ?, NULL, ?)",
++ "INSERT OR IGNORE INTO media_object_view_salts (day, salt) VALUES (?, ?)",
++ "INSERT OR IGNORE INTO media_object_viewer_days (day, object_id, viewer) VALUES (?, ?, ?)",
"INSERT OR IGNORE INTO media_quota_reservations (object_id, app_id, namespace, bytes, expires_at) SELECT id, app_id, namespace, size_bytes, datetime('now', ?) FROM media_objects WHERE lifecycle_status = 'uploading' AND legacy_ref IS NULL",
"INSERT OR IGNORE INTO media_settings (key, value, description, type) VALUES (?, ?, ?, ?)",
"INSERT OR IGNORE INTO paste_likes (paste_id, user_id) VALUES (?, ?)",
@@@ -192,6 +207,8 @@
"SELECT * FROM vods WHERE quarantined_at IS NOT NULL AND quarantined_at <= datetime('now', ?) AND health_status IN ('corrupt','zero_byte','missing_file') AND COALESCE(is_recording, 0) = 0 ORDER BY quarantined_at ASC LIMIT ?",
"SELECT * FROM vods WHERE storage_key LIKE ?",
"SELECT *, COALESCE(duration_seconds, probe_duration_seconds, 0) AS duration_seconds FROM vods WHERE id = ?",
++ "SELECT 1 AS x FROM media_object_tier_decisions WHERE object_id = ? AND action = ? AND outcome = 'failed' AND decided_at >= strftime('%Y-%m-%dT%H:%M:%fZ', 'now', ?) LIMIT 1",
++ "SELECT 1 AS x FROM media_object_tier_decisions WHERE object_id = ? AND action = ? AND outcome = ? AND trigger = 'sweep' AND decided_at >= strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-1 day') LIMIT 1",
"SELECT 1 AS x FROM media_settings WHERE key = 'namespaces.reservations_seeded'",
"SELECT 1 AS x FROM pastes WHERE id = ?",
"SELECT 1 AS x FROM sqlite_master WHERE type = 'table' AND name = ?",
@@@ -234,11 +251,11 @@
"SELECT DISTINCT app_id FROM vods WHERE COALESCE(is_recording, 0) = 0 AND file_path IS NOT NULL",
"SELECT DISTINCT o.app_id, o.namespace FROM media_objects o LEFT JOIN media_namespaces n ON n.namespace = o.namespace WHERE n.namespace IS NULL",
"SELECT EXISTS (SELECT 1 FROM media_holds h WHERE h.released_at IS NULL AND (h.object_id = @id OR h.object_id IN (SELECT r.to_object_id FROM media_relationships r WHERE r.from_object_id = @id AND r.relation = 'clip_of') OR h.object_id IN (SELECT v.object_id FROM clips c JOIN vods v ON v.id = c.vod_id WHERE c.object_id = @id))) AS held",
++ "SELECT MAX(day) AS d FROM media_object_views_daily WHERE object_id = ? AND unique_viewers > 0",
"SELECT SUM(CASE WHEN COALESCE(storage_provider, 'local') = 'local' THEN 1 ELSE 0 END) AS localCount, SUM(CASE WHEN storage_provider = 'b2' THEN 1 ELSE 0 END) AS b2Count, SUM(CASE WHEN storage_provider = 'r2' THEN 1 ELSE 0 END) AS r2Count, SUM(CASE WHEN COALESCE(storage_provider, 'local') = 'local' THEN file_size ELSE 0 END) AS localBytes, SUM(CASE WHEN storage_provider = 'b2' THEN file_size ELSE 0 END) AS b2Bytes, SUM(CASE WHEN storage_provider = 'r2' THEN file_size ELSE 0 END) AS r2Bytes FROM vods WHERE app_id = ?",
"SELECT SUM(CASE WHEN COALESCE(storage_provider, 'local') = 'local' THEN 1 ELSE 0 END) as localCount, SUM(CASE WHEN storage_provider = 'b2' THEN 1 ELSE 0 END) as b2Count, SUM(CASE WHEN storage_provider = 'r2' THEN 1 ELSE 0 END) as r2Count FROM clips",
"SELECT SUM(CASE WHEN COALESCE(storage_provider, 'local') = 'local' THEN 1 ELSE 0 END) as localCount, SUM(CASE WHEN storage_provider = 'b2' THEN 1 ELSE 0 END) as b2Count, SUM(CASE WHEN storage_provider = 'r2' THEN 1 ELSE 0 END) as r2Count, SUM(CASE WHEN COALESCE(storage_provider, 'local') = 'local' THEN file_size ELSE 0 END) as localBytes, SUM(CASE WHEN storage_provider = 'b2' THEN file_size ELSE 0 END) as b2Bytes, SUM(CASE WHEN storage_provider = 'r2' THEN file_size ELSE 0 END) as r2Bytes FROM vods",
"SELECT action, outcome, COUNT(*) AS n FROM media_tier_decisions WHERE app_id = ? AND decided_at >= strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-1 day') GROUP BY action, outcome",
-- "SELECT action, outcome, COUNT(*) AS n FROM media_tier_decisions WHERE decided_at >= strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-1 day') GROUP BY action, outcome",
"SELECT app_id FROM apps ORDER BY app_id",
"SELECT app_id FROM apps WHERE api_key_hash = ?",
"SELECT app_id FROM apps WHERE env = 'sandbox'",
@@@ -263,6 +280,7 @@
"SELECT h.* FROM media_holds h JOIN media_objects o ON o.id = h.object_id WHERE h.id = ? AND o.app_id = ?",
"SELECT h.*, h.object_id AS inherited_from FROM media_holds h WHERE h.released_at IS NULL AND h.object_id != @id AND ( h.object_id IN (SELECT r.to_object_id FROM media_relationships r WHERE r.from_object_id = @id AND r.relation = 'clip_of') OR h.object_id IN (SELECT v.object_id FROM clips c JOIN vods v ON v.id = c.vod_id WHERE c.object_id = @id)) ORDER BY h.id",
"SELECT hash, revision, deleted FROM search_doc_pushes WHERE kind = ? AND media_id = ?",
++ "SELECT id FROM clips WHERE COALESCE(is_public, 1) = 1 AND COALESCE(visibility, 'public') = 'public'",
"SELECT id FROM clips WHERE status = 'failed' AND vod_id IS NOT NULL AND COALESCE(cut_attempts, 0) < ? AND (cut_next_at IS NULL OR cut_next_at <= CURRENT_TIMESTAMP) AND created_at >= datetime('now', '-30 days') AND NOT EXISTS (SELECT 1 FROM media_jobs j WHERE j.job_type = 'clip.cut' AND j.app_id = clips.app_id AND CAST(json_extract(j.params, '$.clip_id') AS INTEGER) = clips.id) ORDER BY created_at DESC LIMIT 4",
"SELECT id FROM clips WHERE status = 'processing'",
"SELECT id FROM media_jobs WHERE id = ? AND status = 'queued'",
@@@ -272,6 +290,7 @@
"SELECT id FROM media_uploads WHERE status IN ('active', 'completing') AND expires_at < datetime('now')",
"SELECT id FROM vods WHERE COALESCE(storage_provider, 'local') = 'local' AND COALESCE(is_recording, 0) = 0 AND created_at <= datetime('now', '-1 day') ORDER BY (last_accessed_at IS NOT NULL), last_accessed_at ASC, view_count ASC, file_size DESC LIMIT 10",
"SELECT id FROM vods WHERE COALESCE(storage_provider, 'local') = 'local' AND COALESCE(is_recording, 0) = 0 AND file_path IS NULL AND created_at <= datetime('now', '-1 hour') AND COALESCE(health_status, 'ok') NOT IN ('missing_file', 'zero_byte')",
++ "SELECT id FROM vods WHERE is_public = 1 AND COALESCE(visibility, 'public') = 'public' AND COALESCE(clips_only, 0) = 0",
"SELECT id FROM vods WHERE is_recording = 1",
"SELECT id, app_id, COALESCE(owner_app, app_id) AS owner_app, owner_user_id FROM media_objects WHERE owner_subject IS NULL AND owner_user_id IS NOT NULL AND id > ? ORDER BY id LIMIT ?",
"SELECT id, app_id, kind, legacy_ref FROM media_objects WHERE id = ?",
@@@ -323,6 +342,7 @@
"SELECT provider, state, checksum, verified_at FROM media_locations WHERE object_id = ? ORDER BY id",
"SELECT r.object_id, r.app_id, r.namespace, o.lifecycle_status, o.legacy_ref, o.metadata FROM media_quota_reservations r LEFT JOIN media_objects o ON o.id = r.object_id WHERE r.expires_at < datetime('now') ORDER BY r.expires_at LIMIT 1000",
"SELECT r.relation, r.to_object_id FROM media_relationships r JOIN media_objects s ON s.id = r.to_object_id WHERE r.from_object_id = ? AND r.relation IN ('derived_from', 'thumbnail_of', 'clip_of') AND s.owner_subject = ? ORDER BY r.id LIMIT 1",
++ "SELECT salt FROM media_object_view_salts WHERE day = ?",
"SELECT screenshot_path FROM pastes WHERE screenshot_path IS NOT NULL",
"SELECT size_bytes FROM media_locations WHERE object_id = ? AND provider = 'local' AND state = 'present'",
"SELECT status FROM media_jobs WHERE id = ?",