fix(growing): don't promote a growing file while its recorder is still recording

The promotion worker promoted on mtime-idle (>=8s), but CIFS attribute caching
makes an actively-growing MXF look idle, so it grabbed the live file ~15s into
recording, uploaded it, flipped the asset live->ready, and unlinked it ("a
worker is stealing the file"). Gate promotion on the recorder's live status:
the growing asset's display_name is the recorder's current_session_id, so skip
promotion while a recorder with that session is status='recording'. Only
promote once recording has stopped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Zac Gaetano 2026-05-31 22:26:07 -04:00
parent 35165e28a8
commit 2cd20a0e72

View file

@ -146,6 +146,23 @@ async function promote(filePath) {
}
const asset = r.rows[0];
// CRITICAL: do not promote while the recorder is STILL RECORDING this
// session. The mtime-idle heuristic is unreliable over CIFS (attribute
// caching makes an actively-growing MXF look "stable"), which caused the
// worker to grab a live file mid-record (~15s in), upload it, flip the
// asset to 'ready', and unlink it — "a worker is stealing the file". The
// growing asset's display_name IS the recorder's current_session_id, so
// gate on the recorder's live status: only promote once recording stopped.
const recActive = await query(
`SELECT 1 FROM recorders
WHERE current_session_id = $1 AND status = 'recording' LIMIT 1`,
[clipName]
);
if (recActive.rows.length > 0) {
// Still recording — leave the growing file in place for the editor.
return;
}
const st = await stat(filePath);
console.log(`[promotion] uploading ${rel} (${st.size} bytes) -> s3://${S3_BUCKET}/${s3Key}`);
await uploadStreamToS3(S3_BUCKET, s3Key, createReadStream(filePath));