diff --git a/src/reels/mod.rs b/src/reels/mod.rs index 2a4e6e9..c5d7492 100644 --- a/src/reels/mod.rs +++ b/src/reels/mod.rs @@ -1095,14 +1095,29 @@ async fn pregen_one( }; let min_generated_at = now - (max_age_hours as i64 * 3600); - let is_fresh = { + // Skip only when a fresh ledger row points at THIS exact cache key (same + // media, params, render version) and its file still exists. Comparing the + // stored cache_key — not just (span, library) — means a key change from + // selection-logic/params drift that doesn't bump RENDER_VERSION still forces + // a regen within the freshness window, instead of leaving a stale row that + // points at an orphaned reel. + let already_current = { let mut dao = app_state.precomputed_reel_dao.lock().expect("lock"); - dao.exists_fresh(&ctx, span, library, RENDER_VERSION as i32, min_generated_at) - .unwrap_or(false) + matches!( + dao.latest_for(&ctx, span, library), + Ok(Some(row)) + if row.cache_key == key + && row.render_version == RENDER_VERSION as i32 + && row.generated_at >= min_generated_at + ) && reel_mp4_path(app_state, &key).exists() }; - if is_fresh { - log::info!("Fresh precomputed reel exists for span={}, skipping", span); + if already_current { + log::info!( + "Fresh precomputed reel already current for span={} key={}, skipping", + span, + key + ); return Ok(()); }