fix(workers): убрать max_retries, который ничего не делает (#2464) #2977

Merged
bot-backend merged 1 commit from fix/2464-inert-retry-config into main 2026-08-20 12:40:07 +00:00
Collaborator

Что не работало

11 celery-тасок объявляли max_retries=2, но ретраи не реализовывали — ни autoretry_for в декораторе, ни вызова self.retry() в теле. Celery в таком виде параметр просто не применяет: при исключении таска падает с первой попытки. Читающий код видит «до 3 попыток», а их одна. Это тот же класс, что concurrency в Forgejo и ON CONFLICT без индекса: объявлено ≠ исполняется.

Правка

Убран max_retries у: cbr_macro_sync, rosstat_macro_sync, developer_registry_refresh, location_refresh, mv_sales_tracker_refresh, refresh_analytics, refresh_layout_velocity, refresh_quarter_price_index, scrape_objective.sync_objective_group, supply_layers_refresh, scrape_kn.scrape_kn_region.

Заодно убран bind=True там, где self не использовался вовсе. В scrape_kn_region он оставленself.request.id пишется в kn_scrape_log; там инертен был только max_retries.

Не тронуты и не должны быть:

таска почему законно
scrape_kn.resume_kn_run max_retries=12 + настоящий self.retry()
nspd_sync, scrape_cadastre autoretry_for в декораторе
nspd_geo, objective_etl.import_anton_objective max_retries=0 — честное «ретраев нет»

Гейт вместо точечной правки

backend/tests/workers/test_2464_retry_config_is_real.py разбирает AST всех модулей app/workers/tasks/: если декоратор объявляет ненулевой max_retries, требуется либо autoretry_for в декораторе, либо self.retry( в теле этой функции. max_retries=0 освобождён — это осмысленное объявление, а не забытый параметр.

Три таски из одиннадцати гейт нашёл сверх списка эпика (refresh_layout_velocity, refresh_quarter_price_index, supply_layers_refresh) — это и есть довод в пользу гейта.

Как проверено

  • Двусторонне: с фиксом зелено; при возврате max_retries=2 в supply_layers_refresh — красно, с указанием именно на эту таску.
  • Контроль от тавтологии: test_gate_sees_the_tasks_at_all требует ≥20 найденных тасок — гейт не может «пройти», ничего не разобрав.
  • Контроль от узости: test_gate_recognises_both_valid_forms — обе законные формы (autoretry_for и self.retry) признаются.
  • pytest backend/tests/workers/ — 229 passed.
  • ruff check backend/app/workers/tasks/ — чисто. Первый прогон поймал F821 self в scrape_kn и заставил вернуть туда bind=True: мой ранний grep приписал все self. в файле соседней таске, ruff показал, что это не так.

Что это меняет на проде

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

Часть эпика #2464.

## Что не работало 11 celery-тасок объявляли `max_retries=2`, но ретраи не реализовывали — ни `autoretry_for` в декораторе, ни вызова `self.retry()` в теле. Celery в таком виде параметр просто не применяет: при исключении таска падает с первой попытки. Читающий код видит «до 3 попыток», а их одна. Это тот же класс, что `concurrency` в Forgejo и `ON CONFLICT` без индекса: **объявлено ≠ исполняется**. ## Правка Убран `max_retries` у: `cbr_macro_sync`, `rosstat_macro_sync`, `developer_registry_refresh`, `location_refresh`, `mv_sales_tracker_refresh`, `refresh_analytics`, `refresh_layout_velocity`, `refresh_quarter_price_index`, `scrape_objective.sync_objective_group`, `supply_layers_refresh`, `scrape_kn.scrape_kn_region`. Заодно убран `bind=True` там, где `self` не использовался вовсе. В `scrape_kn_region` он **оставлен** — `self.request.id` пишется в `kn_scrape_log`; там инертен был только `max_retries`. **Не тронуты и не должны быть:** | таска | почему законно | |---|---| | `scrape_kn.resume_kn_run` | `max_retries=12` + настоящий `self.retry()` | | `nspd_sync`, `scrape_cadastre` | `autoretry_for` в декораторе | | `nspd_geo`, `objective_etl.import_anton_objective` | `max_retries=0` — честное «ретраев нет» | ## Гейт вместо точечной правки `backend/tests/workers/test_2464_retry_config_is_real.py` разбирает AST всех модулей `app/workers/tasks/`: если декоратор объявляет **ненулевой** `max_retries`, требуется либо `autoretry_for` в декораторе, либо `self.retry(` в теле этой функции. `max_retries=0` освобождён — это осмысленное объявление, а не забытый параметр. **Три таски из одиннадцати гейт нашёл сверх списка эпика** (`refresh_layout_velocity`, `refresh_quarter_price_index`, `supply_layers_refresh`) — это и есть довод в пользу гейта. ## Как проверено - **Двусторонне:** с фиксом зелено; при возврате `max_retries=2` в `supply_layers_refresh` — красно, с указанием именно на эту таску. - **Контроль от тавтологии:** `test_gate_sees_the_tasks_at_all` требует ≥20 найденных тасок — гейт не может «пройти», ничего не разобрав. - **Контроль от узости:** `test_gate_recognises_both_valid_forms` — обе законные формы (autoretry_for и self.retry) признаются. - `pytest backend/tests/workers/` — 229 passed. - `ruff check backend/app/workers/tasks/` — чисто. Первый прогон поймал `F821 self` в `scrape_kn` и заставил вернуть туда `bind=True`: мой ранний grep приписал все `self.` в файле соседней таске, ruff показал, что это не так. ## Что это меняет на проде Ничего в поведении: ретраев не было и не будет. Меняется только правдивость кода — параметр, обещавший то, чего нет, убран, и повторно появиться не сможет. Часть эпика #2464.
bot-backend added 1 commit 2026-08-20 12:20:48 +00:00
fix(workers): убрать max_retries, который ничего не делает (#2464)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
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 1m54s
CI / backend-tests (pull_request) Successful in 17m0s
6982255fb3
11 тасок объявляли `max_retries=2`, но ретраи не реализовывали: ни
`autoretry_for` в декораторе, ни вызова `self.retry()` в теле. Celery в
таком виде параметр не применяет — при исключении таска падает с первой
попытки. Читающий код видит «до 3 попыток», а их одна.

Убран `max_retries` у: cbr_macro_sync, rosstat_macro_sync,
developer_registry_refresh, location_refresh, mv_sales_tracker_refresh,
refresh_analytics, refresh_layout_velocity, refresh_quarter_price_index,
scrape_objective.sync_objective_group, supply_layers_refresh,
scrape_kn.scrape_kn_region. Заодно убран `bind=True` там, где `self` не
использовался вовсе; в `scrape_kn_region` он оставлен — `self.request.id`
пишется в kn_scrape_log.

Не тронуты и не должны быть: `resume_kn_run` (max_retries=12 +
настоящий self.retry()), `nspd_sync`/`scrape_cadastre` (autoretry_for),
`nspd_geo`/`objective_etl` (max_retries=0 — честное «ретраев нет»).

Гейт `test_2464_retry_config_is_real.py` разбирает AST всех модулей
`app/workers/tasks/` и требует: если декоратор объявляет ненулевой
max_retries, в нём есть autoretry_for либо в теле функции есть
self.retry(). Три таски из одиннадцати гейт нашёл сверх списка эпика.

Проверка гейта: с фиксом зелено, при возврате `max_retries=2` в
supply_layers_refresh — красно с указанием на эту таску. Плюс два
контроля: гейт видит ≥20 тасок (не молчит из-за пустой выборки) и
признаёт обе законные формы ретраев.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bot-backend merged commit 610ed20395 into main 2026-08-20 12:40:07 +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#2977
No description provided.