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
Collaborator

Пункт эпика #2464: domrf_catalog_object.py:440.

Дефект

db.commit() стоял после блока async with BrowserSession(...). Весь батч жил в одной незакоммиченной транзакции, и любой отказ после цикла — исключение в BrowserSession.__aexit__, снятие Celery-таски, перезапуск контейнера — обнулял все уже успешные UPDATE'ы.

Масштаб

Беговой режим здесь force=True («Загрузить все») → SQL без LIMIT:

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

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

Достижимость — честно

Скрейпер сейчас не отрабатывает вовсе: DOM.РФ отдаёт страницу «Доступ заблокирован [403]» с капчей. Проверил пробой 20.08 через рабочий тракт, подробности в #2443.

Чинить это стоит до разбана, а не после: первый же прогон будет ровно force=True на 13 200 объектов — худший возможный случай для отказа в конце.

Правка

commit после каждого успешного объекта. SAVEPOINT внутри scrape_catalog_object к этому моменту уже снят, поэтому commit корректен.

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

Тест

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

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

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

Прогоны

tests/services/scrapers + tests/workers   519 passed   rc=0
Пункт эпика #2464: `domrf_catalog_object.py:440`. ## Дефект `db.commit()` стоял **после** блока `async with BrowserSession(...)`. Весь батч жил в одной незакоммиченной транзакции, и любой отказ после цикла — исключение в `BrowserSession.__aexit__`, снятие Celery-таски, перезапуск контейнера — обнулял все уже успешные UPDATE'ы. ## Масштаб Беговой режим здесь `force=True` («Загрузить все») → SQL без `LIMIT`: | | | |---|---| | объектов всего | 13 801 | | ни разу не скрейплено | **13 200** (95.7 %) | | последний `catalog_scraped_at` | 2026-05-19 | Многочасовой прогон, где отказ в конце стоит всего. ## Достижимость — честно Скрейпер сейчас не отрабатывает вовсе: DOM.РФ отдаёт страницу «Доступ заблокирован [403]» с капчей. Проверил пробой 20.08 через рабочий тракт, подробности в [#2443](https://git.gendsgn.ru/lekss361/gendesign/issues/2443#issuecomment-26706). Чинить это стоит **до** разбана, а не после: первый же прогон будет ровно `force=True` на 13 200 объектов — худший возможный случай для отказа в конце. ## Правка `commit` после каждого успешного объекта. SAVEPOINT внутри `scrape_catalog_object` к этому моменту уже снят, поэтому commit корректен. Финальный `commit` оставлен намеренно: он закрывает транзакцию, которую могли autobegin'ить неудачные итерации (их SAVEPOINT откатился, а внешняя транзакция открыта), и сохраняет прежнее поведение для вызывающих. ## Тест Не ходит ни в сеть, ни в БД: `BrowserSession` и `scrape_catalog_object` подменены, сессия — счётчик вызовов. Против `origin/main`: ``` 4 успеха + отказ на выходе → зафиксировано 0 раз вместо ≥4 → падает 3 успеха из 6 → 1 фиксация вместо 4 → падает пустой батч не трогает сессию → контроль, зелёный с обеих сторон батч без успехов закрывает tx → контроль, зелёный с обеих сторон ``` Второй контроль стоит не для симметрии: он ловит «починку», которая выкинула бы финальный commit, решив, что по-объектных достаточно. ## Прогоны ``` tests/services/scrapers + tests/workers 519 passed rc=0 ```
bot-backend added 1 commit 2026-08-20 08:35:33 +00:00
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
238e0ef1d6
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>
bot-backend merged commit edbaca1e87 into main 2026-08-20 08:54:27 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2960
No description provided.