From bec64e668d91831316b84c3149628add4c0559ee Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Tue, 26 May 2026 07:35:13 -0400 Subject: [PATCH] fix(conform): mark asset error on failure; scope asset lookup by project_id (issue #94 bugs 1, 9) --- services/worker/src/workers/conform.js | 37 +++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/services/worker/src/workers/conform.js b/services/worker/src/workers/conform.js index d764f15..2713ad1 100644 --- a/services/worker/src/workers/conform.js +++ b/services/worker/src/workers/conform.js @@ -127,10 +127,30 @@ export const conformWorker = async (job) => { await job.updateProgress(Math.min(5 + (processedEdits / edits.length) * 50, 55)); console.log(`[conform] Processing edit ${edit.editNumber}: ${edit.reelName}`); - const assetRes = await query( - 'SELECT id, original_s3_key FROM assets WHERE filename = $1 LIMIT 1', - [edit.reelName] - ); + // BUG FIX #9: Scope asset lookup by project_id to prevent cross-project + // collisions when two projects contain assets with the same filename. + let assetRes; + if (projectId) { + assetRes = await query( + `SELECT id, original_s3_key FROM assets + WHERE filename = $1 AND project_id = $2 + LIMIT 1`, + [edit.reelName, projectId] + ); + // Fall back to unscoped lookup if no match in the current project + // (EDL reel names may reference assets not yet assigned to a project) + if (assetRes.rows.length === 0) { + assetRes = await query( + 'SELECT id, original_s3_key FROM assets WHERE filename = $1 LIMIT 1', + [edit.reelName] + ); + } + } else { + assetRes = await query( + 'SELECT id, original_s3_key FROM assets WHERE filename = $1 LIMIT 1', + [edit.reelName] + ); + } if (assetRes.rows.length === 0) { throw new Error(`Asset not found for reel: ${edit.reelName}`); @@ -201,6 +221,15 @@ export const conformWorker = async (job) => { } catch (error) { console.error(`[conform] Error in job ${jobId}:`, error); + // BUG FIX #1: Mark the output asset (if any) as 'error' so the UI doesn't + // show a perpetually-spinning 'processing' state when the conform fails. + // We don't have an assetId until the INSERT succeeds, so target by job key. + await query( + `UPDATE assets + SET status = 'error', updated_at = NOW() + WHERE original_s3_key = $1`, + [`jobs/${jobId}/conformed.mp4`] + ).catch(e => console.error('[conform] Failed to mark asset error:', e.message)); throw error; } finally { await Promise.all([