You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
55 lines
1.9 KiB
55 lines
1.9 KiB
/** Audita trabajos interrumpidos. --limpiar retira solo huérfanos de más de 24 h. */
|
|
import { readdir, readFile, rm, stat } from 'node:fs/promises';
|
|
import { resolve, join, sep } from 'node:path';
|
|
import pg from 'pg';
|
|
const raices = [
|
|
resolve(process.env.MEDIA_DIR ?? 'media/audio'),
|
|
resolve(process.env.ESCUCHA_DIR ?? 'media/escucha'),
|
|
resolve(process.env.ONDA_DIR ?? 'static/ondas')
|
|
];
|
|
const limpiar = process.argv.includes('--limpiar');
|
|
const carpeta = join(raices[0], '.procesando');
|
|
const nombres = await readdir(carpeta).catch((f) => {
|
|
if (f.code === 'ENOENT') return [];
|
|
throw f;
|
|
});
|
|
const cliente = new pg.Client({ connectionString: process.env.DATABASE_URL });
|
|
await cliente.connect();
|
|
try {
|
|
for (const nombre of nombres.filter((n) => /^[a-f0-9-]{36}\.trabajo\.json$/.test(n))) {
|
|
const ruta = join(carpeta, nombre),
|
|
datos = JSON.parse(await readFile(ruta, 'utf8'));
|
|
if (
|
|
!Array.isArray(datos.temporales) ||
|
|
!Array.isArray(datos.finales) ||
|
|
!Array.isArray(datos.claves)
|
|
)
|
|
throw new Error('Manifiesto no válido');
|
|
const archivos = [...datos.temporales, ...datos.finales];
|
|
if (
|
|
archivos.some(
|
|
(p) => typeof p !== 'string' || !raices.some((r) => resolve(p).startsWith(r + sep))
|
|
)
|
|
)
|
|
throw new Error('Manifiesto fuera del almacén');
|
|
const { rows } = await cliente.query('select clave from medio where clave=any($1::text[])', [
|
|
datos.claves
|
|
]);
|
|
const antiguo = Date.now() - (await stat(ruta)).mtimeMs > 86400000;
|
|
const estado = rows.length
|
|
? 'registrado: conservar archivos'
|
|
: antiguo
|
|
? 'huérfano recuperable'
|
|
: 'reciente: no tocar';
|
|
console.log(`${datos.slug}: ${estado}`);
|
|
if (limpiar && antiguo) {
|
|
// Una representación registrada basta para conservar TODOS los finales.
|
|
for (const archivo of rows.length ? datos.temporales : archivos)
|
|
await rm(archivo, { force: true });
|
|
await rm(ruta);
|
|
}
|
|
}
|
|
} finally {
|
|
await cliente.end();
|
|
}
|