Keep artifact list and beta queries free of file bytes

This commit is contained in:
2026-10-06 14:01:12 -04:00
parent 27be1abf41
commit ddb3db9537
21 changed files with 197 additions and 101 deletions
+2
View File
@@ -11,6 +11,7 @@ import { initializeFleetSettings } from './fleet-settings.js';
import { migrateServerHistory } from './server-history.js';
import { migrateNativeInstances } from '../backends/schema.js';
import { installPerformanceIndexes } from './performance-indexes.js';
import { migrateVersionLayout } from './version-layout.js';
import { timeStatement } from './slow-statements.js';
let _db: Database.Database | null = null;
@@ -388,6 +389,7 @@ export function db(): Database.Database {
backfillLeaderboard(handle);
initializeFleetSettings(handle);
migrateNativeInstances(handle);
migrateVersionLayout(handle);
// Lifecycle history is retained indefinitely. Admission and status reads
// must narrow by server or active state instead of scanning that history.
// Install after migrations that rebuild this table or add server_deleted_at.
+1 -1
View File
@@ -130,11 +130,11 @@ CREATE TABLE IF NOT EXISTS script_versions (
release_version TEXT, -- publisher's version/tag, independent of upload order
sha256 TEXT NOT NULL,
size INTEGER NOT NULL,
content BLOB NOT NULL,
notes TEXT,
state TEXT NOT NULL DEFAULT 'untested', -- 'untested' | 'tested' | 'test-failed'
kind TEXT NOT NULL DEFAULT 'script', -- denormalized from scripts.kind for join-free filtering
uploaded_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
content BLOB NOT NULL,
UNIQUE(script_id, version)
);
CREATE INDEX IF NOT EXISTS idx_script_versions_script ON script_versions(script_id);
+27
View File
@@ -0,0 +1,27 @@
import type Database from 'better-sqlite3';
/** Keep metadata ahead of overflow pages, preserving IDs and all references. */
export function migrateVersionLayout(handle: Database.Database): void {
const columns = handle.pragma('table_info(script_versions)') as { name: string }[];
if (columns.at(-1)?.name === 'content') return;
const { sql } = handle.prepare("SELECT sql FROM sqlite_master WHERE name='script_versions'").get() as { sql: string };
const content = /\bcontent\s+BLOB\s+NOT\s+NULL\s*,/i;
if (!content.test(sql)) throw new Error('Unrecognized script version content layout');
const replacement = sql.replace(content, '').replace(/,\s*UNIQUE\s*\(/i, ', content BLOB NOT NULL, UNIQUE(')
.replace('script_versions', 'script_versions_metadata');
const dependents = handle.prepare("SELECT sql FROM sqlite_master WHERE tbl_name='script_versions' AND type IN ('index','trigger') AND sql IS NOT NULL")
.all() as { sql: string }[];
const sequence = handle.prepare("SELECT seq FROM sqlite_sequence WHERE name='script_versions'").get() as { seq: number } | undefined;
handle.pragma('foreign_keys = OFF');
try {
handle.transaction(() => {
handle.exec(replacement);
const names = columns.map(column => `"${column.name}"`).join(',');
handle.exec(`INSERT INTO script_versions_metadata (${names}) SELECT ${names} FROM script_versions;
DROP TABLE script_versions; ALTER TABLE script_versions_metadata RENAME TO script_versions;`);
if (sequence) handle.prepare("UPDATE sqlite_sequence SET seq=MAX(seq,?) WHERE name='script_versions'").run(sequence.seq);
for (const dependent of dependents) handle.exec(dependent.sql);
if ((handle.pragma('foreign_key_check') as unknown[]).length) throw new Error('Version layout migration found broken references');
})();
} finally { handle.pragma('foreign_keys = ON'); }
}