From 0f8707fe93ec16b182dd22e40a8551b1d046fb32 Mon Sep 17 00:00:00 2001 From: StenFredd Date: Sun, 3 May 2026 14:12:25 +0300 Subject: [PATCH] retry --- src/worker.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/worker.py b/src/worker.py index cb41226..cef844c 100644 --- a/src/worker.py +++ b/src/worker.py @@ -335,6 +335,51 @@ async def download_manga( "source_slug": auth_slug, "finished_at": finished_ts}) return + # ── Автоповтор неудачных глав (до 3 раз) ───────────────────── + MAX_AUTO_RETRIES = 3 + for retry_attempt in range(1, MAX_AUTO_RETRIES + 1): + stats = await db_call(db.get_chapter_stats, url) + if stats["failed"] + stats["partial"] == 0: + break + failed_count = stats["failed"] + stats["partial"] + logger.info( + "Автоповтор {}/{}: {} неудачных/частичных глав для {}", + retry_attempt, MAX_AUTO_RETRIES, failed_count, url, + ) + await emit({ + "type": "retry_errors_auto", + "url": url, + "attempt": retry_attempt, + "max_attempts": MAX_AUTO_RETRIES, + "failed_count": failed_count, + }) + await db_call(db.reset_failed_chapters, url) + all_ch_rows = await db_call(db.get_all_chapters, url) + pending_urls = {c["chapter_url"] for c in all_ch_rows if c["status"] == "pending"} + retry_chapters = [ch for ch in manga.chapters if ch.url in pending_urls] + if not retry_chapters: + break + retry_results = await asyncio.gather( + *[process_chapter(ch) for ch in retry_chapters], + return_exceptions=True, + ) + auth_slug = None + for ch, res in zip(retry_chapters, retry_results): + if isinstance(res, AuthRequiredError): + auth_slug = res.source_slug + elif isinstance(res, Exception) and not isinstance(res, asyncio.CancelledError): + logger.exception( + "retry {}: необработанное исключение Т{} Гл.{} '{}': {}", + retry_attempt, ch.volume, ch.number, ch.title, res, + ) + if auth_slug: + await db_call(db.update_manga_status, url, "stopped") + await db_call(db.set_manga_last_error, url, f"auth_required:{auth_slug}") + finished_ts = await db_call(db.mark_finished, url) + await emit({"type": "auth_required", "url": url, + "source_slug": auth_slug, "finished_at": finished_ts}) + return + real_done = await db_call(db.sync_chapters_done, url) await db_call(db.update_manga_status, url, "done") finished_ts = await db_call(db.mark_finished, url)