Skip to content

Commit 6718981

Browse files
committed
feat: Enhance download error handling with fallback mechanisms and reduced retry limits
1 parent c607489 commit 6718981

File tree

1 file changed

+84
-11
lines changed

1 file changed

+84
-11
lines changed

app/core/downloader.py

Lines changed: 84 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,17 +226,20 @@ def _ydl_download(
226226
dest_dir / (_sanitize_filename(title_hint or "%(title)s") + ".%(ext)s")
227227
)
228228
logger.debug(f"yt-dlp output template: {outtmpl}")
229+
# Keep retries conservative to avoid endless retry loops on dead links
229230
ydl_opts: Dict[str, Any] = {
230231
"outtmpl": outtmpl,
231-
"retries": 5,
232+
"retries": 3, # whole-request retries
233+
"fragment_retries": 3, # per-fragment retries
232234
"continuedl": True,
233235
"concurrent_fragment_downloads": 4,
234236
"quiet": True,
235237
"noprogress": True,
236238
"merge_output_format": "mkv",
237-
"fragment_retries": 9999,
238239
"downloader": "ffmpeg",
239240
"hls_use_mpegts": True,
241+
# Fail faster on broken CDNs
242+
"socket_timeout": 20,
240243
}
241244

242245
# Apply proxy for yt-dlp if configured
@@ -339,15 +342,85 @@ def download_episode(
339342
base_hint = f"{slug}-S{season:02d}E{episode:02d}-{language}-{chosen}"
340343
logger.debug(f"Generated base_hint for filename: {base_hint}")
341344

342-
temp_path, info = _ydl_download(
343-
direct,
344-
dest_dir,
345-
title_hint=base_hint,
346-
cookiefile=cookiefile,
347-
progress_cb=progress_cb,
348-
stop_event=stop_event,
349-
force_no_proxy=force_no_proxy,
350-
)
345+
try:
346+
temp_path, info = _ydl_download(
347+
direct,
348+
dest_dir,
349+
title_hint=base_hint,
350+
cookiefile=cookiefile,
351+
progress_cb=progress_cb,
352+
stop_event=stop_event,
353+
force_no_proxy=force_no_proxy,
354+
)
355+
except Exception as e:
356+
# If the actual download fails (timeouts/CDN issues), try one controlled
357+
# fallback path before giving up:
358+
# 1) If we used proxy, re-resolve and download without proxy consistently
359+
# 2) Otherwise, try to re-resolve with a different provider if available
360+
msg = str(e)
361+
logger.warning(f"Primary download failed: {msg}")
362+
363+
# Attempt no-proxy re-resolution+download if proxy was in play
364+
tried_alt = False
365+
if PROXY_ENABLED and not force_no_proxy and PROXY_SCOPE in ("all", "ytdlp"):
366+
try:
367+
with disabled_proxy_env():
368+
ep2 = build_episode(
369+
link=link, slug=slug, season=season, episode=episode
370+
)
371+
direct2, chosen2 = get_direct_url_with_fallback(
372+
ep2, preferred=provider, language=language
373+
)
374+
logger.info(
375+
f"Retrying download without proxy using provider {chosen2}"
376+
)
377+
temp_path, info = _ydl_download(
378+
direct2,
379+
dest_dir,
380+
title_hint=base_hint,
381+
cookiefile=cookiefile,
382+
progress_cb=progress_cb,
383+
stop_event=stop_event,
384+
force_no_proxy=True,
385+
)
386+
tried_alt = True
387+
except Exception as e2:
388+
logger.error(f"No-proxy fallback download failed: {e2}")
389+
# fall through to final error or other alt attempts
390+
391+
if not tried_alt:
392+
# As a last resort, try a different provider once (if any available)
393+
try:
394+
providers_left = [p for p in PROVIDER_ORDER if p != (provider or "")]
395+
for p in providers_left:
396+
try:
397+
direct3, chosen3 = get_direct_url_with_fallback(
398+
ep, preferred=p, language=language
399+
)
400+
logger.info(
401+
f"Retrying download via alternate provider {chosen3}"
402+
)
403+
temp_path, info = _ydl_download(
404+
direct3,
405+
dest_dir,
406+
title_hint=base_hint,
407+
cookiefile=cookiefile,
408+
progress_cb=progress_cb,
409+
stop_event=stop_event,
410+
force_no_proxy=force_no_proxy,
411+
)
412+
tried_alt = True
413+
break
414+
except Exception as e3:
415+
logger.warning(
416+
f"Alternate provider {p} failed to download: {e3}"
417+
)
418+
except Exception as e4:
419+
logger.debug(f"Alternate-provider resolution failed: {e4}")
420+
421+
if not tried_alt:
422+
# Give up with the original failure
423+
raise
351424

352425
logger.info(f"Download complete, renaming to release schema.")
353426
final_path = rename_to_release(

0 commit comments

Comments
 (0)