fix(site_finder): SAVEPOINT-isolate gate-lookup db.execute swallows (#2464 Wave 2) #2468

Merged
bot-backend merged 1 commit from worktree-agent-ad881375834cdfd40 into main 2026-07-08 06:46:05 +00:00
Collaborator

Что

Волна 2 эпика #2464, часть 2/3 — gate-lookups + разное (10 swallow-сайтов в 8 файлах). Найдено completeness-sweep'ом.

Баг-класс

Каждый сайт на общей analyze/report-сессии ловил сбой db.execute и возвращал фолбэк без rollback → транзакция aborted → следующий db.execute в запросе падает. Фикс — SAVEPOINT with db.begin_nested(): на swallow-сайте.

Файл Функция Паттерн
krt_lookup.py parcel_krt_requisites (×2: exact + fallback query) begin_nested
okn_lookup.py parcel_okn_objects begin_nested
ppt_tep_lookup.py parcel_ppt_tep begin_nested
riasurt_lookup.py parcel_riasurt_gate begin_nested
premises_lookup.py resolve_cad_for_domrf begin_nested
ird_analyze.py _krt_at begin_nested (row-shaping вынесен за with)
product_scoring.py _poi_weight_sum (×2: centroid + compute_poi_weighted_top7) begin_nested
locations.py compute_location_indices pass-1 infra/POI db.rollback() — owned

locations.py — плоский rollback(), не savepoint: единственная цепочка compute_location_indicesrefresh_locationsworkers/tasks/location_refresh.py, который открывает свой SessionLocal() (owned, недельный Celery-refresh, не shared). Pass-1 read-only (нечего терять); pass-2 UPSERT-цикл уже правильно использует begin_nested (там bare rollback затёр бы уже-upsert'нутые районы). Reviewer независимо подтвердил цепочку grep'ом.

product_scoring._poi_weight_sumдва swallow-сайта в одной функции (centroid-lookup + вызов compute_poi_weighted_top7, чей callee poi_score.py делает незащищённый db.execute и пропагирует). Оба обёрнуты. Единственный другой caller compute_poi_weighted_top7 (parcels.py:4609) — POST-роут, пропагирует в 500, не swallow.

Фолбэки и типы except байт-в-байт неизменны.

Тесты

Регресс-тест на каждый сайт: сбой db.execute → фолбэк сохранён → begin_nested (или для locations — rollback, и begin_nested НЕ вызван) → следующий db.execute на той же сессии успешен. Фейки с реальным begin_nested-CM (не наивный мок). tests/services/site_finder + forecasting = 1718+ passed, ruff чисто.

Ревью

code-reviewer: ⚠️ MINOR (оба минора закрыты в этом PR) → по сути . Проверены shape SAVEPOINT, независимая верификация locations.py owned-цепочки, _krt_at row-shaping-move, второй poi-сайт (был живой gap в целевой функции), отсутствие :x::type, отсутствие tradein.

Refs #2464 (cluster A, Wave 2 · 2/3).

## Что Волна 2 эпика **#2464**, часть 2/3 — gate-lookups + разное (10 swallow-сайтов в 8 файлах). Найдено completeness-sweep'ом. ### Баг-класс Каждый сайт на **общей** analyze/report-сессии ловил сбой `db.execute` и возвращал фолбэк **без rollback** → транзакция `aborted` → следующий `db.execute` в запросе падает. Фикс — SAVEPOINT `with db.begin_nested():` на swallow-сайте. | Файл | Функция | Паттерн | |---|---|---| | `krt_lookup.py` | `parcel_krt_requisites` (×2: exact + fallback query) | `begin_nested` | | `okn_lookup.py` | `parcel_okn_objects` | `begin_nested` | | `ppt_tep_lookup.py` | `parcel_ppt_tep` | `begin_nested` | | `riasurt_lookup.py` | `parcel_riasurt_gate` | `begin_nested` | | `premises_lookup.py` | `resolve_cad_for_domrf` | `begin_nested` | | `ird_analyze.py` | `_krt_at` | `begin_nested` (row-shaping вынесен за `with`) | | `product_scoring.py` | `_poi_weight_sum` (×2: centroid + `compute_poi_weighted_top7`) | `begin_nested` | | `locations.py` | `compute_location_indices` pass-1 infra/POI | **`db.rollback()`** — owned | **`locations.py` — плоский `rollback()`, не savepoint**: единственная цепочка `compute_location_indices` ← `refresh_locations` ← `workers/tasks/location_refresh.py`, который открывает свой `SessionLocal()` (owned, недельный Celery-refresh, не shared). Pass-1 read-only (нечего терять); pass-2 UPSERT-цикл уже правильно использует `begin_nested` (там bare rollback затёр бы уже-upsert'нутые районы). Reviewer независимо подтвердил цепочку grep'ом. `product_scoring._poi_weight_sum` — **два** swallow-сайта в одной функции (centroid-lookup + вызов `compute_poi_weighted_top7`, чей callee `poi_score.py` делает незащищённый `db.execute` и пропагирует). Оба обёрнуты. Единственный другой caller `compute_poi_weighted_top7` (`parcels.py:4609`) — POST-роут, пропагирует в 500, не swallow. Фолбэки и типы `except` байт-в-байт неизменны. ## Тесты Регресс-тест на каждый сайт: сбой `db.execute` → фолбэк сохранён → `begin_nested` (или для locations — `rollback`, и `begin_nested` НЕ вызван) → следующий `db.execute` на той же сессии успешен. Фейки с реальным `begin_nested`-CM (не наивный мок). `tests/services/site_finder` + `forecasting` = **1718+ passed**, ruff чисто. ## Ревью code-reviewer: ⚠️ MINOR (оба минора закрыты в этом PR) → по сути ✅. Проверены shape SAVEPOINT, независимая верификация `locations.py` owned-цепочки, `_krt_at` row-shaping-move, второй poi-сайт (был живой gap в целевой функции), отсутствие `:x::type`, отсутствие tradein. Refs #2464 (cluster A, Wave 2 · 2/3).
bot-backend added 1 commit 2026-07-08 06:19:57 +00:00
fix(backend): SAVEPOINT-isolate cluster-A db.execute swallows (batch 2) (#2464)
All checks were successful
CI / changes (pull_request) Successful in 8s
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / backend-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 2m1s
CI / backend-tests (pull_request) Successful in 15m19s
ce714ecf79
krt_lookup (×2), okn_lookup, ppt_tep_lookup, riasurt_lookup, premises_lookup,
ird_analyze._krt_at, and product_scoring._poi_weight_sum (both the centroid
lookup and the compute_poi_weighted_top7 call) swallowed db.execute failures
without a SAVEPOINT, leaving the shared analyze/report session aborted for
later queries. Wrap each swallow site in db.begin_nested(). locations.py's
pass-1 infra/POI block uses a plain db.rollback() instead — its session is
owned by the weekly location_refresh Celery task (own SessionLocal, verified
single caller-chain), not shared, and nothing is pending at that point.

Refs #2464 (cluster A session-poisoning, Wave 2).
bot-backend merged commit 01360e9c3d into main 2026-07-08 06:46:05 +00:00
bot-backend deleted branch worktree-agent-ad881375834cdfd40 2026-07-08 06:46:05 +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#2468
No description provided.