Feature/resolve probe fairness (#636)

* Added Resolve - Probe fairness to avoid probe starvation
* Added Probe setting to setup wizard
* Playlist sort order fix
This commit is contained in:
euzu
2026-03-08 14:53:05 +01:00
committed by GitHub
parent b6c2817fcb
commit 497a75e0bb
20 changed files with 602 additions and 228 deletions
+18 -12
View File
@@ -1174,6 +1174,15 @@ async fn playlist_probe(ctx: &PlaylistProcessingContext, target: &ConfigTarget,
if needs_live_probe(&item, cutoff_ts) {
if let Some(provider_id) = provider_id_from_item(&item) {
if queued_live_keys.insert(provider_id.clone()) {
let task = UpdateTask::ProbeLive {
id: provider_id.clone(),
reason: ResolveReasonSet::from_variants(&[ResolveReason::Probe]),
delay: probe_delay,
interval: interval_secs,
};
if mgr.is_redundant_with_pending_task(input_name.as_ref(), &task) {
continue;
}
if log_enabled!(Level::Debug) {
let last_probed = match item.header.additional_properties.as_ref() {
Some(StreamProperties::Live(props)) => props.last_probed_timestamp,
@@ -1184,12 +1193,6 @@ async fn playlist_probe(ctx: &PlaylistProcessingContext, target: &ConfigTarget,
input_name, provider_id, last_probed, cutoff_ts, interval_secs, item.header.title
);
}
let task = UpdateTask::ProbeLive {
id: provider_id,
reason: ResolveReasonSet::from_variants(&[ResolveReason::Probe]),
delay: probe_delay,
interval: interval_secs,
};
mgr.queue_task_background(input_name.clone(), task);
queued_live_count += 1;
}
@@ -1238,18 +1241,21 @@ async fn playlist_probe(ctx: &PlaylistProcessingContext, target: &ConfigTarget,
continue;
}
debug!(
"[Task] Creating ProbeStream task for input {}: scope={}, unique_id={}, item_type={:?}, title=\"{}\"",
input_name, probe_scope, unique_id, item.header.item_type, item.header.title
);
let task = UpdateTask::ProbeStream {
probe_scope,
unique_id,
probe_scope: probe_scope.clone(),
unique_id: unique_id.clone(),
url: item.header.url.to_string(),
item_type: item.header.item_type,
reason: ResolveReasonSet::from_variants(&[ResolveReason::MissingDetails]),
delay: opts.probe_delay,
};
if mgr.is_redundant_with_pending_task(input_name.as_ref(), &task) {
continue;
}
debug!(
"[Task] Creating ProbeStream task for input {}: scope={}, unique_id={}, item_type={:?}, title=\"{}\"",
input_name, probe_scope, unique_id, item.header.item_type, item.header.title
);
mgr.queue_task_background(input_name.clone(), task);
queued_stream_count += 1;
}
@@ -207,25 +207,27 @@ fn queue_background_series_info(
let reasons = check_resolve_reasons(resolve_options, resolve_tmdb_enabled, pli);
if !reasons.is_empty() {
if log_enabled!(Level::Debug) {
let has_details = pli.has_details();
let (has_tmdb, has_date) = match pli.header.additional_properties.as_ref() {
Some(StreamProperties::Series(props)) => {
(props.tmdb.is_some(), props.release_date.is_some())
}
_ => (false, false),
};
debug!(
"[Task] Creating ResolveSeries task for input {}: id={}, reasons={}, has_details={}, has_tmdb={}, has_date={}, title=\"{}\"",
input_name_arc, provider_id, reasons, has_details, has_tmdb, has_date, pli.header.title
);
}
let task = UpdateTask::ResolveSeries {
id: provider_id,
id: provider_id.clone(),
reason: reasons,
delay: resolve_options.resolve_delay,
};
mgr.queue_task_background(input_name_arc.clone(), task);
if !mgr.is_redundant_with_pending_task(input_name_arc.as_ref(), &task) {
if log_enabled!(Level::Debug) {
let has_details = pli.has_details();
let (has_tmdb, has_date) = match pli.header.additional_properties.as_ref() {
Some(StreamProperties::Series(props)) => {
(props.tmdb.is_some(), props.release_date.is_some())
}
_ => (false, false),
};
debug!(
"[Task] Creating ResolveSeries task for input {}: id={}, reasons={}, has_details={}, has_tmdb={}, has_date={}, title=\"{}\"",
input_name_arc, provider_id, reasons, has_details, has_tmdb, has_date, pli.header.title
);
}
mgr.queue_task_background(input_name_arc.clone(), task);
}
}
}
@@ -441,6 +441,12 @@ fn queue_background_vod_info(
let reasons = check_resolve_reasons(resolve_options, do_probe, resolve_tmdb_enabled, pli);
if !reasons.is_empty() {
let task =
UpdateTask::ResolveVod { id: provider_id.clone(), reason: reasons, delay: resolve_options.resolve_delay };
if mgr.is_redundant_with_pending_task(input.name.as_ref(), &task) {
continue;
}
if log_enabled!(Level::Debug) {
let has_details = pli.has_details();
let (has_tmdb, has_date, has_video, has_audio) =
@@ -461,8 +467,6 @@ fn queue_background_vod_info(
input.name, provider_id, reasons, has_details, has_tmdb, has_date, has_video, has_audio, pli.header.title
);
}
let task =
UpdateTask::ResolveVod { id: provider_id, reason: reasons, delay: resolve_options.resolve_delay };
mgr.queue_task_background(input.name.clone(), task);
}
}