diff --git a/services/mam-api/src/index.js b/services/mam-api/src/index.js index 1ba708a..01b18b7 100644 --- a/services/mam-api/src/index.js +++ b/services/mam-api/src/index.js @@ -32,6 +32,7 @@ import metricsRouter from './routes/metrics.js'; import commentsRouter from './routes/comments.js'; import importsRouter from './routes/imports.js'; import { startSchedulerLoop } from './scheduler.js'; +import { startCleanupLoop } from './tasks/cleanupTempSegments.js'; const app = express(); const PORT = process.env.PORT || 3000; @@ -196,4 +197,7 @@ app.listen(PORT, () => { // Boot the recorder scheduler tick loop after the HTTP server is live so // the loop's self-calls to /recorders/:id/start|stop reach a ready socket. startSchedulerLoop(); + + // Boot the temp-segment cleanup loop (runs hourly). + startCleanupLoop(); }); diff --git a/services/mam-api/src/tasks/cleanupTempSegments.js b/services/mam-api/src/tasks/cleanupTempSegments.js new file mode 100644 index 0000000..1401eb6 --- /dev/null +++ b/services/mam-api/src/tasks/cleanupTempSegments.js @@ -0,0 +1,41 @@ +import pool from '../db/pool.js'; +import { deleteObject } from '../s3/client.js'; + +const CLEANUP_INTERVAL_MS = 3600_000; + +let _interval = null; + +async function cleanup() { + const expired = await pool.query( + 'SELECT * FROM temp_segments WHERE expires_at < NOW()' + ); + + if (expired.rows.length === 0) return; + + let deleted = 0; + let errors = 0; + + for (const segment of expired.rows) { + try { + await deleteObject(segment.s3_key); + await pool.query('DELETE FROM temp_segments WHERE id = $1', [segment.id]); + deleted++; + } catch (err) { + console.error('[cleanup] failed to delete segment ' + segment.id + ': ' + err.message); + errors++; + } + } + + console.log(`[cleanup] temp segments: ${deleted} deleted, ${errors} errors`); +} + +export function startCleanupLoop() { + if (_interval) return; + console.log(`[cleanup] temp segments loop started (interval=${CLEANUP_INTERVAL_MS}ms)`); + cleanup().catch(() => {}); + _interval = setInterval(() => cleanup().catch(() => {}), CLEANUP_INTERVAL_MS); +} + +export function stopCleanupLoop() { + if (_interval) { clearInterval(_interval); _interval = null; } +}