diff --git a/services/mam-api/src/routes/jobs.js b/services/mam-api/src/routes/jobs.js index 8227006..a2f8cd0 100644 --- a/services/mam-api/src/routes/jobs.js +++ b/services/mam-api/src/routes/jobs.js @@ -81,6 +81,37 @@ async function getAllBullMQJobs() { return results; } +// Mutate `jobs` in place to fill in asset_name from the assets table for any +// job that has an assetId but no inline assetName in its payload. One bulk +// SQL query per refresh — cheap, and means we don't have to remember to pass +// assetName at every enqueue site (upload.js, capture stop, scheduler, etc.). +async function attachAssetNames(jobs) { + const idsNeedingLookup = [...new Set( + jobs.filter(j => j.asset_id && !j.asset_name).map(j => j.asset_id) + )]; + if (idsNeedingLookup.length === 0) return; + + let rows = []; + try { + const result = await pool.query( + 'SELECT id, display_name, filename FROM assets WHERE id = ANY($1::uuid[])', + [idsNeedingLookup] + ); + rows = result.rows; + } catch { + // If the lookup fails (DB down, bad UUID in a stale BullMQ payload), keep + // serving jobs without names rather than 500-ing the whole list. + return; + } + const byId = new Map(rows.map(r => [r.id, r.display_name || r.filename])); + for (const j of jobs) { + if (j.asset_id && !j.asset_name) { + const name = byId.get(j.asset_id); + if (name) j.asset_name = name; + } + } +} + // ── GET /events – Server-Sent Events stream of live job updates ─────────────── router.get('/events', async (req, res) => { res.setHeader('Content-Type', 'text/event-stream'); @@ -96,6 +127,7 @@ router.get('/events', async (req, res) => { if (closed) return; try { const jobs = await getAllBullMQJobs(); + await attachAssetNames(jobs); if (!closed) res.write(`data: ${JSON.stringify({ type: 'jobs', jobs })}\n\n`); } catch (err) { if (!closed) res.write(`data: ${JSON.stringify({ type: 'error', message: err.message })}\n\n`); @@ -111,6 +143,7 @@ router.get('/', async (req, res, next) => { try { const { type, status, asset_id } = req.query; let jobs = await getAllBullMQJobs(); + await attachAssetNames(jobs); if (type) jobs = jobs.filter(j => j.type === type); if (status) jobs = jobs.filter(j => j.status === status); @@ -138,7 +171,9 @@ router.get('/:id', async (req, res, next) => { if (job) { const state = await job.getState(); const apiStatus = STATE_MAP[state] || state; - return res.json(normalizeJob(job, type, apiStatus)); + const normalized = normalizeJob(job, type, apiStatus); + await attachAssetNames([normalized]); + return res.json(normalized); } } catch { /* try next queue */ } }