fix(ptica): успехи батча каталога фиксируются по ходу, а не одним commit'ом в конце (#2464) #2960

Merged
bot-backend merged 1 commit from fix/2464-catalog-batch-commits into main 2026-08-20 08:54:27 +00:00

1 commit

Author SHA1 Message Date
238e0ef1d6 fix(ptica): успехи батча каталога фиксируются по ходу, а не одним commit'ом в конце (#2464)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m25s
CI / backend-tests (pull_request) Successful in 17m26s
scrape_catalog_objects держал весь батч в одной незакоммиченной транзакции:
db.commit() стоял ПОСЛЕ блока `async with BrowserSession(...)`. Любой отказ после
цикла — исключение в BrowserSession.__aexit__, снятие Celery-таски, перезапуск
контейнера — обнулял все уже успешные UPDATE'ы.

Масштаб не гипотетический. Беговой режим здесь force=True («Загрузить все»), то
есть SQL без LIMIT:

  объектов всего              13801
  ни разу не скрейплено       13200  (95.7%)
  последний catalog_scraped_at  2026-05-19

Это многочасовой прогон, где отказ в конце стоит всего.

Про достижимость честно: скрейпер сейчас не отрабатывает вовсе — DOM.РФ отдаёт
страницу «Доступ заблокирован [403]» с капчей (проба 20.08, подробности в #2443).
Чинить это стоит ДО разбана, а не после: первый же прогон будет как раз force=True
на 13200 объектов, то есть худший возможный случай.

Правка: commit после каждого успешного объекта. SAVEPOINT внутри
scrape_catalog_object к этому моменту уже снят, поэтому commit корректен.
Финальный commit оставлен — он закрывает транзакцию, которую могли autobegin'ить
неудачные итерации, и сохраняет прежнее поведение для вызывающих.

Тест не ходит в сеть и в БД: BrowserSession и scrape_catalog_object подменены,
сессия — счётчик вызовов. Против origin/main:

  4 успеха + отказ на выходе  → зафиксировано 0 раз вместо >=4  → падает
  3 успеха из 6               → 1 фиксация вместо 4             → падает
  пустой батч не трогает сессию   — контроль, зелёный с обеих сторон
  батч без успехов закрывает tx   — контроль, зелёный с обеих сторон

Второй контроль стоит не для симметрии: он ловит «починку», которая выкинула бы
финальный commit, решив, что по-объектных достаточно.

Прогоны: tests/services/scrapers + tests/workers — 519 passed rc=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 13:35:05 +05:00