Skip to content

Commit bd83b50

Browse files
mjcCopilot
andcommitted
Fix three VMAF calc state management bugs
1. Resolve 'will retry' failures on success: When CRF search retry succeeds and transitions to crf_searched, resolve any unresolved CRF search failures for that video. Previously 24+ encoded videos had stale unresolved failure records. 2. Reset state when sync deletes VMAFs: When video_upsert detects metadata changes and deletes VMAFs, also reset crf_searched videos back to analyzed. Previously sync could nuke VMAFs via delete_vmafs_for_video without fixing the state, leaving 486+ invalid crf_searched videos with no VMAF data. 3. Run reset_crf_searched_without_vmaf periodically: Schedule the orphan reset every 5 minutes instead of only on encoder startup. Acts as a safety net for any future state inconsistencies. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 0be3501 commit bd83b50

3 files changed

Lines changed: 26 additions & 0 deletions

File tree

lib/reencodarr/ab_av1/crf_search.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ defmodule Reencodarr.AbAv1.CrfSearch do
547547
defp transition_to_crf_searched(video) do
548548
case Retry.retry_on_db_busy(fn -> Media.mark_as_crf_searched(video) end) do
549549
{:ok, _} ->
550+
Media.resolve_crf_search_failures(video.id)
550551
:ok
551552

552553
{:error, reason} ->

lib/reencodarr/encoder/broadway/producer.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ defmodule Reencodarr.Encoder.Broadway.Producer do
1212

1313
# Poll every 2 seconds to check for new work
1414
@poll_interval_ms 2000
15+
# Reset orphaned/invalid states every 5 minutes
16+
@orphan_reset_interval_ms 300_000
1517

1618
# After 900 consecutive unavailable polls (~30 minutes), attempt recovery
1719
@recovery_threshold 900
@@ -31,6 +33,7 @@ defmodule Reencodarr.Encoder.Broadway.Producer do
3133
def init(_opts) do
3234
send(self(), :reset_orphaned)
3335
schedule_poll()
36+
schedule_orphan_reset()
3437
{:producer, %{pending_demand: 0, consecutive_unavailable: 0}}
3538
end
3639

@@ -51,6 +54,7 @@ defmodule Reencodarr.Encoder.Broadway.Producer do
5154
def handle_info(:reset_orphaned, state) do
5255
Media.reset_orphaned_encoding()
5356
Media.reset_crf_searched_without_vmaf()
57+
schedule_orphan_reset()
5458
{:noreply, [], state}
5559
end
5660

@@ -93,6 +97,10 @@ defmodule Reencodarr.Encoder.Broadway.Producer do
9397
Process.send_after(self(), :poll, @poll_interval_ms)
9498
end
9599

100+
defp schedule_orphan_reset do
101+
Process.send_after(self(), :reset_orphaned, @orphan_reset_interval_ms)
102+
end
103+
96104
# Public for testing
97105
@doc false
98106
# :available means encoder responded and is free — reset counter

lib/reencodarr/media/video_upsert.ex

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,28 @@ defmodule Reencodarr.Media.VideoUpsert do
147147
if not being_marked_encoded and
148148
VideoValidator.should_delete_vmafs?(existing_video, new_values) do
149149
delete_vmafs_for_video(existing_video.id)
150+
reset_crf_searched_state(existing_video.id)
150151
end
151152

152153
:ok
153154
end
154155

156+
# When VMAFs are deleted during sync, any crf_searched video must be reset to
157+
# analyzed — the old VMAF data is invalid and the video needs re-searching.
158+
defp reset_crf_searched_state(video_id) do
159+
{count, _} =
160+
from(v in Video,
161+
where: v.id == ^video_id and v.state == :crf_searched
162+
)
163+
|> Repo.update_all(
164+
set: [state: :analyzed, chosen_vmaf_id: nil, updated_at: DateTime.utc_now()]
165+
)
166+
167+
if count > 0 do
168+
Logger.info("Reset crf_searched video #{video_id} → analyzed after VMAF deletion")
169+
end
170+
end
171+
155172
@spec handle_bitrate_preservation(
156173
%{String.t() => any()},
157174
map() | nil,

0 commit comments

Comments
 (0)