import { BaseCommand } from '@adonisjs/core/ace' import { CommandOptions } from '@adonisjs/core/types/ace' import db from '@adonisjs/lucid/services/db' const BATCH = 50_000 /** * One-off (LOG.md 2026-10-08 (14)): copies the content types and archive * listings still on `files` into file_details, a partition at a time. * Values written since the deploy (by the new code, into file_details) win: * a file that has details already is skipped. */ export default class FilesMoveDetails extends BaseCommand { public static commandName = 'files:move-details' public static description = "Copies files' content types and archive listings into file_details." public static options: CommandOptions = { startApp: true, } public async run() { const { rows: partitions } = await db.rawQuery( `SELECT c.relname FROM pg_inherits i JOIN pg_class c ON c.oid = i.inhrelid WHERE i.inhparent = 'files'::regclass ORDER BY c.relname` ) let total = 0 for (const { relname } of partitions) { const started = Date.now() const { rows } = await db.rawQuery(`SELECT min(id) AS lo, max(id) AS hi FROM ${relname}`) if (rows[0].lo === null) continue let copied = 0 // Short statements in id order: one statement over a whole partition took 30 minutes, and the // garbage filter deleted files meanwhile, which failed the foreign key (LOG.md 2026-10-08 (15)). for (let lo = Number(rows[0].lo); lo <= Number(rows[0].hi); lo += BATCH) { for (let attempt = 1; ; attempt++) { try { const result = await db.rawQuery( `INSERT INTO file_details (file_id, content_type, archive) SELECT id, content_type, archive FROM ${relname} WHERE id >= ? AND id < ? AND (content_type IS NOT NULL OR archive IS NOT NULL) ON CONFLICT (file_id) DO NOTHING`, [lo, lo + BATCH] ) copied += result.rowCount ?? 0 break } catch (error: any) { // A file deleted while this batch ran: the batch again, without it. if (error.code !== '23503' || attempt >= 5) throw error } } } total += copied this.logger.info(`${relname}: ${copied} copied in ${Math.round((Date.now() - started) / 1000)} s.`) } this.logger.info(`${total} files' details copied.`) } }