fix(ops): не хоронить источник после одного пустого прогона
All checks were successful
Deploy / test (push) Successful in 11m54s
Deploy / deploy (push) Successful in 8s

Сторож считал источник исчерпанным, если прошлый прогон не добавил и не
выбрал ни одной статьи. Но ровно так же выглядит обрыв связи с API и прогон
на устаревшем коде парсера: сегодня CORE после единственной неудачи был
помечен исчерпанным и больше не запускался — молча, без ошибки в интерфейсе.

Теперь нужно два пустых прогона подряд. Разовый сбой переживём, а реально
кончившийся источник остановится всего на один прогон позже.

Заодно таймаут запроса к CORE снижен с 60 до 30 секунд: три попытки по
минуте отъедали 180 секунд из 1500 бюджета на одной залипшей странице —
та же грабля, что чинили в pmc_bulk. Обычный ответ приходит за 7 секунд.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
jze9
2026-09-16 18:34:14 +05:00
parent 263a521d63
commit 9123844a87
2 changed files with 23 additions and 8 deletions

View File

@@ -115,12 +115,25 @@ def main() -> None:
started = []
for source_id, source_type, last_run_id in sources:
# Источник исчерпан, если прошлый прогон не добавил ни одной статьи
# и не был отменён: дальше в дампе/бакете для нас ничего нет
# Источник исчерпан, если прогоны перестали добавлять статьи: дальше
# в дампе/бакете/выдаче для нас ничего нет.
#
# Но ОДИН пустой прогон — ещё не приговор: ровно так же выглядят
# обрыв связи с API и прогон на устаревшем коде парсера. На CORE
# 16.09.2026 из-за этого источник был помечен исчерпанным после
# единственной неудачи и больше не запускался — молча, без ошибки.
# Поэтому ждём два пустых прогона подряд: разовый сбой переживём,
# а реально кончившийся источник остановится всего на один прогон
# позже.
if last_run_id and not args.keep_going_empty:
prev = s.get(ParseRun, last_run_id)
if prev and prev.status == "done" and prev.added == 0 and prev.fetched == 0:
print(f"{source_type}: источник исчерпан, пропускаем")
last_two = s.execute(text("""
SELECT status, added, fetched FROM parse_runs
WHERE source_id = :sid ORDER BY id DESC LIMIT 2
"""), {"sid": source_id}).all()
if len(last_two) == 2 and all(
r.status == "done" and r.added == 0 and r.fetched == 0 for r in last_two
):
print(f"{source_type}: источник исчерпан (два пустых прогона), пропускаем")
continue
src = s.get(ParseSource, source_id)