diff --git a/app/scheduler/deep_crawl.py b/app/scheduler/deep_crawl.py index 330fe85..2ebe9f0 100644 --- a/app/scheduler/deep_crawl.py +++ b/app/scheduler/deep_crawl.py @@ -39,6 +39,13 @@ _PAGE_CAP: dict[str, int] = { "xvideoscom": 1800, } +# Miękki budżet czasu na run (s). Detail-fetch scrapery (per-scena fetch strony, np. +# przez wolne proxy) potrafią przekroczyć hard-timeout 3600s z _job_deep_crawl → run +# ubijany w locie, kursor NIE zapisany (orphan thread), tube zero postępu + alert +# GOON-V. Budżet < hard-timeout: przerywamy PO skończonej stronie, zapisujemy kursor, +# wracamy czysto — następny run kontynuuje. Margines 600s na dokończenie strony w toku. +_RUN_BUDGET_SEC = 3000 + def _state_path() -> Path: return Path(getattr(get_settings(), "deepcrawl_state_path", None) or _DEFAULT_STATE) @@ -119,6 +126,7 @@ def run_deep_crawl(*, pages_per_run: int = 60, sitetags: list[str] | None = None t0 = time.time() last_done = start - 1 exhausted = False + budget_hit = False if cap is not None and start > cap: # kursor osiągnął per-tube cap → traktuj jak koniec katalogu (reset re-sweepuje od 1) @@ -141,7 +149,17 @@ def run_deep_crawl(*, pages_per_run: int = 60, sitetags: list[str] | None = None except Exception: counters["errors"] += 1 last_done = page - if cap is not None and last_done >= cap: + # Miękki budżet: stop po skończonej stronie (kursor=last_done zapisany niżej), + # zanim hard-timeout ubije run mid-page (orphan thread, kursor zgubiony — GOON-V). + if time.time() - t0 > _RUN_BUDGET_SEC: + budget_hit = True + log.warning( + "deep-crawl %s: run budget %ds hit at page %d (%d/%d stron) — stop czysto, " + "kursor zapisany, kontynuacja w następnym runie", + sitetag, _RUN_BUDGET_SEC, page, page - start + 1, pages_per_run, + ) + break + if not budget_hit and cap is not None and last_done >= cap: log.info("deep-crawl %s: reached page cap %d (exhausted)", sitetag, cap) exhausted = True @@ -152,7 +170,10 @@ def run_deep_crawl(*, pages_per_run: int = 60, sitetags: list[str] | None = None _save_state(state) log.info( - "deep-crawl %s pages %d-%d: %s exhausted=%s (%.0fs)", - sitetag, start, last_done, counters, exhausted, time.time() - t0, + "deep-crawl %s pages %d-%d: %s exhausted=%s budget_hit=%s (%.0fs)", + sitetag, start, last_done, counters, exhausted, budget_hit, time.time() - t0, ) - return {"sitetag": sitetag, "start": start, "end": last_done, "exhausted": exhausted, **counters} + return { + "sitetag": sitetag, "start": start, "end": last_done, + "exhausted": exhausted, "budget_hit": budget_hit, **counters, + }