diff --git a/services/mam-api/src/routes/assets.js b/services/mam-api/src/routes/assets.js index 8b222d6..a8c6cfd 100644 --- a/services/mam-api/src/routes/assets.js +++ b/services/mam-api/src/routes/assets.js @@ -74,7 +74,8 @@ router.get('/', async (req, res, next) => { } if (search) { - query += ` AND (a.display_name ILIKE $${paramCount} OR a.notes ILIKE $${paramCount})`; + // Search display_name, filename, and notes — filename was previously omitted + query += ` AND (a.display_name ILIKE $${paramCount} OR a.filename ILIKE $${paramCount} OR a.notes ILIKE $${paramCount})`; params.push(`%${search}%`); paramCount++; } @@ -203,6 +204,28 @@ router.post('/', async (req, res, next) => { } }); +// POST /cleanup-live – mark stuck 'live' assets as 'error' +// +// Recorder containers that crash without calling the stop callback leave +// assets permanently in 'live' status. This endpoint recovers them. +// Default age threshold: 4 hours. Accepts ?max_age_hours=N override. +router.post('/cleanup-live', async (req, res, next) => { + try { + const maxAgeHours = Math.max(1, parseInt(req.query.max_age_hours || '4', 10)); + const result = await pool.query( + `UPDATE assets + SET status = 'error', updated_at = NOW() + WHERE status = 'live' + AND created_at < NOW() - ($1 * INTERVAL '1 hour') + RETURNING id, display_name, project_id, created_at`, + [maxAgeHours] + ); + res.json({ cleaned: result.rowCount, assets: result.rows }); + } catch (err) { + next(err); + } +}); + // GET /:id - Single asset router.get('/:id', async (req, res, next) => { try {