(medium) corp_sum: сбой парсера оставляет run помеченным 'done' (silent failure) — асимметрия с фиксом lots_pf #1220 #1369

Closed
opened 2026-06-14 18:09:49 +00:00 by bot-backend · 1 comment
Collaborator

Описание

В ветке corp_sum счётчик reports_ok += 1 инкрементируется на строке 329 СРАЗУ после fetch+save_raw, ДО попытки парсинга. Парсинг (parse_corp_sum) выполняется в try/except на строках 330-353; при его падении except Exception as parse_err (строка 344) делает rollback + log, но не инкрементирует reports_failed и не откатывает reports_ok. В результате при сбое парсера главного отчёта корпусов run помечается status='done' (строка 376, т.к. reports_failed == 0) с rows_corpus_room=0. Downstream и GlitchTip видят успешный прогон, хотя нормализованных данных нет.

Корень

Асимметрия с веткой lots_pf, которую явно ИСПРАВИЛ комментарий #1220 (строки 266-273): там reports_ok += 1 стоит ПОСЛЕ успешного db.commit() (строка 300), а inner-except инкрементирует reports_failed += 1 (строка 304). Ветка corp_sum осталась без зеркального фикса: ранний инкремент reports_ok (329) до парсинга + отсутствие reports_failed += 1 в её except.

Evidence

scrape_objective.py:329-353:

reports_ok += 1  # строка 329, ДО парсинга
try:
    if kind == "corp_sum":
        n = parser_mod.parse_corp_sum(payload, group, raw_id, db, dry_run=False)
        ...
    db.commit()
except Exception as parse_err:
    db.rollback()
    logger.exception(...)   # НЕ reports_failed += 1, reports_ok НЕ откатывается

scrape_objective.py:373-377:

_finish_run(db, run_id, status="done" if reports_failed == 0 else "failed", ...)

Контраст — lots_pf ветка (строки 298-304): db.commit(); n_requests += 1; reports_ok += 1 и except ...: reports_failed += 1.

Suggested fix

Зеркалить фикс #1220 для corp_sum: переместить reports_ok += 1 на ПОСЛЕ успешного db.commit() парсера и добавить reports_failed += 1 в except Exception as parse_err. Тогда сбой парсера главного отчёта корректно пометит run как 'failed' и всплывёт в Celery/GlitchTip.

Severity-обоснование

medium: данных нет, но и внешнего сигнала об ошибке нет — классический silent-success. Путь достижим в проде (любой KeyError/ValueError/constraint в parse_corp_sum). Критичным было бы при записи ошибочных данных; здесь данные просто отсутствуют, поэтому medium.


week ревью 1 · multi-agent аудит 2026-06-14 · severity=medium · category=error-handling

Затронутые файлы:

  • /Users/anton/Птица/gendesign/backend/app/workers/tasks/scrape_objective.py
## Описание В ветке corp_sum счётчик `reports_ok += 1` инкрементируется на строке 329 СРАЗУ после fetch+save_raw, ДО попытки парсинга. Парсинг (`parse_corp_sum`) выполняется в try/except на строках 330-353; при его падении `except Exception as parse_err` (строка 344) делает rollback + log, но **не** инкрементирует `reports_failed` и **не** откатывает `reports_ok`. В результате при сбое парсера главного отчёта корпусов run помечается `status='done'` (строка 376, т.к. `reports_failed == 0`) с `rows_corpus_room=0`. Downstream и GlitchTip видят успешный прогон, хотя нормализованных данных нет. ## Корень Асимметрия с веткой lots_pf, которую явно ИСПРАВИЛ комментарий #1220 (строки 266-273): там `reports_ok += 1` стоит ПОСЛЕ успешного `db.commit()` (строка 300), а inner-except инкрементирует `reports_failed += 1` (строка 304). Ветка corp_sum осталась без зеркального фикса: ранний инкремент `reports_ok` (329) до парсинга + отсутствие `reports_failed += 1` в её except. ## Evidence `scrape_objective.py:329-353`: ```python reports_ok += 1 # строка 329, ДО парсинга try: if kind == "corp_sum": n = parser_mod.parse_corp_sum(payload, group, raw_id, db, dry_run=False) ... db.commit() except Exception as parse_err: db.rollback() logger.exception(...) # НЕ reports_failed += 1, reports_ok НЕ откатывается ``` `scrape_objective.py:373-377`: ```python _finish_run(db, run_id, status="done" if reports_failed == 0 else "failed", ...) ``` Контраст — lots_pf ветка (строки 298-304): `db.commit(); n_requests += 1; reports_ok += 1` и `except ...: reports_failed += 1`. ## Suggested fix Зеркалить фикс #1220 для corp_sum: переместить `reports_ok += 1` на ПОСЛЕ успешного `db.commit()` парсера и добавить `reports_failed += 1` в `except Exception as parse_err`. Тогда сбой парсера главного отчёта корректно пометит run как 'failed' и всплывёт в Celery/GlitchTip. ## Severity-обоснование **medium**: данных нет, но и внешнего сигнала об ошибке нет — классический silent-success. Путь достижим в проде (любой KeyError/ValueError/constraint в `parse_corp_sum`). Критичным было бы при записи ошибочных данных; здесь данные просто отсутствуют, поэтому medium. --- _week ревью 1 · multi-agent аудит 2026-06-14 · severity=**medium** · category=`error-handling`_ Затронутые файлы: - `/Users/anton/Птица/gendesign/backend/app/workers/tasks/scrape_objective.py`
bot-backend added the
week ревью 1
label 2026-06-14 18:09:49 +00:00
bot-backend added the
scope/backend
label 2026-06-15 11:01:53 +00:00
Owner

🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)

Текущее состояние кода: backend/app/workers/tasks/scrape_objective.py:329reports_ok += 1 СРАЗУ после _save_raw, ДО парсинга. Парсинг в try/except :330-353; except Exception as parse_err: (:344-353) делает db.rollback() + logger.exception, но НЕ инкрементирует reports_failed и НЕ откатывает reports_ok. _finish_run (:373-377) ставит status="done" if reports_failed == 0 else "failed".

Корень: асимметрия с веткой lots_pf, исправленной по #1220. Ветка lots_pf (:298-309) корректно: db.commit(); n_requests += 1; reports_ok += 1 ПОСЛЕ успеха, а её except (:301-309) делает n_requests += 1; reports_failed += 1. Комментарий :266-273 явно объясняет, что счётчики инкрементятся только после commit — но corp_sum-ветка этот паттерн не зеркалит. Результат: сбой parse_corp_sum → run помечен done с rows_corpus_room=0; downstream/GlitchTip видят успех, хотя нормализованных данных нет (silent success).

Что править:

  • Зеркалить фикс #1220 для corp_sum: убрать reports_ok += 1 со :329, перенести на ПОСЛЕ успешного db.commit() (:343), внутри try.
  • В except Exception as parse_err: (:344) добавить reports_failed += 1 (рядом с db.rollback()).
  • Сверить, что n_requests += 1 для corp_sum остаётся корректным (он на :314 после method(**params) — это сам HTTP-запрос, его учёт независим от парсинга; lots_pf считает n_requests в обеих ветках try/except, corp_sum считает один раз до парсинга — оставить как есть либо привести к единому стилю).

Что посмотреть:

  • Код: scrape_objective.py функция sync_objective_group (:255-384), сравнить lots_pf-ветку (:274-309) и corp_sum-ветку (:310-353); _finish_run логика reports_failed == 0. Тест: замокать parse_corp_sum на raise → проверить, что run помечен failed и reports_failed >= 1.
  • Vault: релевантных заметок не найдено (фикс #1220 — в истории issue, не в vault).
**🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)** **Текущее состояние кода:** `backend/app/workers/tasks/scrape_objective.py:329` — `reports_ok += 1` СРАЗУ после `_save_raw`, ДО парсинга. Парсинг в try/except `:330-353`; `except Exception as parse_err:` (`:344-353`) делает `db.rollback()` + `logger.exception`, но НЕ инкрементирует `reports_failed` и НЕ откатывает `reports_ok`. `_finish_run` (`:373-377`) ставит `status="done" if reports_failed == 0 else "failed"`. **Корень:** асимметрия с веткой lots_pf, исправленной по #1220. Ветка lots_pf (`:298-309`) корректно: `db.commit(); n_requests += 1; reports_ok += 1` ПОСЛЕ успеха, а её `except` (`:301-309`) делает `n_requests += 1; reports_failed += 1`. Комментарий `:266-273` явно объясняет, что счётчики инкрементятся только после commit — но corp_sum-ветка этот паттерн не зеркалит. Результат: сбой `parse_corp_sum` → run помечен `done` с `rows_corpus_room=0`; downstream/GlitchTip видят успех, хотя нормализованных данных нет (silent success). **Что править:** - Зеркалить фикс #1220 для corp_sum: убрать `reports_ok += 1` со `:329`, перенести на ПОСЛЕ успешного `db.commit()` (`:343`), внутри try. - В `except Exception as parse_err:` (`:344`) добавить `reports_failed += 1` (рядом с `db.rollback()`). - Сверить, что `n_requests += 1` для corp_sum остаётся корректным (он на `:314` после `method(**params)` — это сам HTTP-запрос, его учёт независим от парсинга; lots_pf считает n_requests в обеих ветках try/except, corp_sum считает один раз до парсинга — оставить как есть либо привести к единому стилю). **Что посмотреть:** - Код: `scrape_objective.py` функция `sync_objective_group` (`:255-384`), сравнить lots_pf-ветку (`:274-309`) и corp_sum-ветку (`:310-353`); `_finish_run` логика `reports_failed == 0`. Тест: замокать `parse_corp_sum` на raise → проверить, что run помечен `failed` и `reports_failed >= 1`. - Vault: релевантных заметок не найдено (фикс #1220 — в истории issue, не в vault).
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
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#1369
No description provided.