video: longer adaptive slskd wait + stop the automations page blink
two issues: 1. slskd search gave up at 22s (then stopped the search), but slskd gathers peers over its full ~60s window — so most movie searches were killed before results arrived. now waits up to 55s but returns early once results SETTLE (12+ hits, or no new hits for ~12s) so fast searches don't burn the whole window. matches the music side's longer wait. 2. the automations page re-rendered the WHOLE system section every 8s poll (replaceChild) → blink + wiped the socket's live progress. now it skips the rebuild unless something structural changed (added/removed/toggled/ran); live progress comes via socket, the countdown ticks locally.
This commit is contained in:
parent
b55c245fe6
commit
8fe73ac924
3 changed files with 39 additions and 6 deletions
|
|
@ -261,11 +261,17 @@ def _fail_or_retry(db, dl, error_msg) -> None:
|
|||
_archive_history(db, dl, {"status": "failed", "error": err, "completed_at": completed})
|
||||
|
||||
|
||||
def _search_for_retry(query, max_seconds=22):
|
||||
"""A bounded blocking slskd search for the retry worker (shorter than the UI's).
|
||||
def _search_for_retry(query, max_seconds=55):
|
||||
"""A bounded blocking slskd search for the retry worker + the auto-grab automation.
|
||||
|
||||
slskd gathers peer responses over its full search window (~60s by default), so a short
|
||||
wait misses almost everything. We poll up to ``max_seconds`` but return EARLY once
|
||||
results have arrived and settled — break on either plenty of hits (12+) or no new hits
|
||||
for ~12s after getting some, so fast searches don't burn the whole window.
|
||||
|
||||
Always STOPS the slskd search when done — otherwise it keeps running its full timeout
|
||||
(~60s) and, since the bounded auto-grab fires searches back-to-back, they pile up on
|
||||
slskd. Stopping each one keeps concurrent slskd searches ≈ the worker pool size."""
|
||||
and, since the auto-grab fires searches back-to-back, they pile up. Stopping each one
|
||||
keeps concurrent slskd searches ≈ the worker pool size."""
|
||||
from core.video.slskd_search import poll_search, start_search, stop_search
|
||||
res = start_search(query)
|
||||
sid = res.get("id")
|
||||
|
|
@ -273,11 +279,20 @@ def _search_for_retry(query, max_seconds=22):
|
|||
return {"hits": [], "total_files": 0}
|
||||
deadline = time.monotonic() + max_seconds
|
||||
last = {"hits": [], "total_files": 0}
|
||||
prev, settle = 0, 0 # track hit growth; settle = consecutive no-growth polls (~1.5s each)
|
||||
try:
|
||||
while time.monotonic() < deadline:
|
||||
last = poll_search(sid)
|
||||
if len(last.get("hits") or []) >= 12:
|
||||
break
|
||||
n = len(last.get("hits") or [])
|
||||
if n >= 12:
|
||||
break # plenty — stop waiting
|
||||
if n > prev:
|
||||
settle = 0 # still arriving — keep waiting
|
||||
elif n > 0:
|
||||
settle += 1
|
||||
if settle >= 8: # ~12s with no new hits → results have settled
|
||||
break
|
||||
prev = n
|
||||
time.sleep(1.5)
|
||||
return last
|
||||
finally:
|
||||
|
|
|
|||
|
|
@ -103,6 +103,13 @@ def test_video_page_exposes_reload_hook():
|
|||
|
||||
# --- the System list is shown in a logical pipeline order -----------------
|
||||
|
||||
def test_video_automations_poll_does_not_rebuild_when_unchanged():
|
||||
# regression: the 8s poll used to replaceChild the whole section every time → blink +
|
||||
# wiped live progress. It must skip the rebuild when nothing structural changed.
|
||||
assert 'if (sig === _lastSig) return;' in _VAUTO
|
||||
assert 'var sig = JSON.stringify(' in _VAUTO
|
||||
|
||||
|
||||
def test_video_system_automations_are_sorted_by_pipeline_order():
|
||||
# The API returns newest-created-first (jumbled); the page re-sorts by an
|
||||
# explicit order so it reads scans → processors → library → maintenance.
|
||||
|
|
|
|||
|
|
@ -91,10 +91,21 @@
|
|||
'<span class="auto-stat"><strong>' + sys.length + '</strong> System</span>';
|
||||
}
|
||||
|
||||
var _lastSig = null;
|
||||
function load() {
|
||||
return getJSON('/api/automations').then(function (d) {
|
||||
var all = Array.isArray(d) ? d : (d && d.automations) || [];
|
||||
var sys = sortSystem(all.filter(isVideoAutomation));
|
||||
// Re-rendering the whole System section every 8s poll destroys + recreates every
|
||||
// card — that's the blink, and it wipes the live progress the socket patches in.
|
||||
// Only rebuild when something STRUCTURAL changed (added/removed/toggled/ran);
|
||||
// live progress arrives via socket, the "Next: in Xm" countdown ticks locally.
|
||||
var sig = JSON.stringify(sys.map(function (a) {
|
||||
return [a.id, a.enabled, a.name, a.trigger_type, a.action_type,
|
||||
a.last_run, a.next_run, a.run_count, a.last_result];
|
||||
}));
|
||||
if (sig === _lastSig) return;
|
||||
_lastSig = sig;
|
||||
renderStats(sys);
|
||||
renderSystem(sys);
|
||||
renderHubOnce();
|
||||
|
|
|
|||
Loading…
Reference in a new issue