fix(scheduler): опечатка в city расписания падает, а не собирает Екатеринбург
All checks were successful
CI Trade-In / changes (pull_request) Successful in 11s
CI / changes (pull_request) Successful in 14s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m53s

CI ветки краснел на test_job_avito_city_sweep_unknown_city_falls_back_to_none:
тест закреплял прежний контракт «неизвестный слаг → anchors=None», а реестр теперь
бросает ValueError вместо молчаливого отката на ЕКБ.

Правильное поведение — падать. anchors=None уводит свип на EKB_ANCHORS, то есть
опечатка в default_params.city давала полноценный прогон по Екатеринбургу,
проштампованный именем чужого города. Тик планировщика ValueError ловит
(logger.exception в _run), цикл не умирает — крашится только этот прогон.

Отсутствие ключа city по-прежнему даёт anchors=None и citywide-свип ЕКБ: это
контракт старых расписаний, он не тронут. Комментарий на call-site приведён в
соответствие — он всё ещё описывал возврат None.
This commit is contained in:
bot-backend 2026-09-15 20:45:47 +03:00
parent 4646c3b79e
commit 450940cafb
2 changed files with 14 additions and 9 deletions

View file

@ -550,17 +550,20 @@ async def test_job_avito_city_sweep_without_city_param_falls_back_to_none() -> N
assert kwargs["anchors"] is None assert kwargs["anchors"] is None
async def test_job_avito_city_sweep_unknown_city_falls_back_to_none() -> None: async def test_job_avito_city_sweep_unknown_city_raises_instead_of_sweeping() -> None:
"""Неизвестный city slug (typo/будущий город без CITY_ANCHORS-записи) → anchors=None, """Неизвестный city slug (опечатка в расписании) обязан упасть, а не собрать ЕКБ.
НЕ падает с KeyError. Раньше `get_city_anchors` отдавал None, и свип уходил на EKB_ANCHORS: опечатка в
`default_params.city` тихо давала прогон по Екатеринбургу, проштампованный чужим
городом. Теперь реестр падает с ValueError; прогон крашится, а тик планировщика
это ловит (`logger.exception` в `_run`, scheduler.py) цикл не умирает, но и
мусора в корпус не попадает.
""" """
with patch.object(kit_sched, "run_avito_city_sweep", AsyncMock()) as mock_run: with patch.object(kit_sched, "run_avito_city_sweep", AsyncMock()) as mock_run:
await _job_avito_city_sweep(MagicMock(), 1, {"city": "nonexistent_town"}, _oblast_ctx()) with pytest.raises(ValueError, match="nonexistent_town"):
await _job_avito_city_sweep(MagicMock(), 1, {"city": "nonexistent_town"}, _oblast_ctx())
mock_run.assert_awaited_once() mock_run.assert_not_awaited()
_args, kwargs = mock_run.call_args
assert kwargs["anchors"] is None
# ── #2616: _job_avito_full_load(_exhaustive) прокидывает ctx.proxy_provider ────── # ── #2616: _job_avito_full_load(_exhaustive) прокидывает ctx.proxy_provider ──────

View file

@ -1058,8 +1058,10 @@ async def _job_avito_city_sweep(
db: Session, run_id: int, params: dict[str, Any], ctx: SchedulerContext db: Session, run_id: int, params: dict[str, Any], ctx: SchedulerContext
) -> None: ) -> None:
# #B1 oblast rollout: default_params["city"] (slug, e.g. "nizhniy_tagil") → anchors # #B1 oblast rollout: default_params["city"] (slug, e.g. "nizhniy_tagil") → anchors
# города вместо EKB_ANCHORS. Отсутствует/неизвестен → get_city_anchors вернёт None → # города вместо EKB_ANCHORS. Ключа нет вовсе → anchors=None → citywide-свип ЕКБ
# run_avito_city_sweep сам падает на EKB_ANCHORS (прежнее поведение без city). # (прежнее поведение расписаний без city). Ключ ЕСТЬ, но слаг неизвестен →
# get_city_anchors падает с ValueError: опечатка в расписании раньше тихо давала
# прогон по Екатеринбургу под именем чужого города.
city = params.get("city") city = params.get("city")
anchors = get_city_anchors(city) if city else None anchors = get_city_anchors(city) if city else None
await run_avito_city_sweep( await run_avito_city_sweep(