import { BaseCommand } from '@adonisjs/core/ace' import { CommandOptions } from '@adonisjs/core/types/ace' import db from '@adonisjs/lucid/services/db' /** * 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 result = await db.rawQuery( `INSERT INTO file_details (file_id, content_type, archive) SELECT id, content_type, archive FROM ${relname} WHERE content_type IS NOT NULL OR archive IS NOT NULL ON CONFLICT (file_id) DO NOTHING` ) total += result.rowCount ?? 0 this.logger.info(`${relname}: ${result.rowCount} copied in ${Math.round((Date.now() - started) / 1000)} s.`) } this.logger.info(`${total} files' details copied.`) } }