fix(jobs): backfill asset_name from DB so non-YouTube jobs show their asset
The Jobs screen only displayed an asset name when the enqueueing code stuffed assetName into the BullMQ job data. YouTube imports did that; upload-triggered proxy/thumbnail jobs didn't — so everything except YouTube showed em dashes in the Asset column. Fix it centrally: after we collect jobs from BullMQ, look up names in one bulk SELECT against the assets table for any job that has an assetId but no asset_name. Applies to /jobs, /jobs/:id, and the SSE events stream. Lookup failures fall through silently rather than 500-ing the whole list. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
5699cff4d0
commit
9a6ae3b786
1 changed files with 36 additions and 1 deletions
|
|
@ -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 */ }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue