fix(tradein): data-layer tail A2+B+C — trgm index, FDW options, matview refresh (Refs #769) #804

Merged
bot-reviewer merged 1 commit from fix/769-data-layer-a2b2c into main 2026-05-30 17:40:54 +00:00
Collaborator

Что

Хвост #769 (A1+D смержены в #798; E отложен — geo-radius client-facing risk). Закрывает A2/B/C — все низкорисковые, не клиентские.

A2 (#10, index) — 086_deals_address_trgm_index.sql

deals.address не имел GIN-trgm индекса → seq-scan на street-match. pg_trgm + CREATE INDEX IF NOT EXISTS deals_address_trgm_idx ... gin(address gin_trgm_ops). Идемпот, plain CREATE INDEX (txn-safe).

B (#13, FDW) — 087_fdw_server_options.sql

gendesign_remote без fetch_size/use_remote_estimate → плохое планирование 6.8M-row FDW import. DO-block читает pg_foreign_server.srvoptionsADD-or-SET для каждой опции (идемпотентно при любом prior-state), RAISE если сервера нет.

C (#14, matview) — scheduler.py + 088_*.sql

Находка: listings_search_mv активно читается search_query.py (/api/v1/search) но никогда не рефрешился (refresh_search_matview.py существует, в beat/scheduler отсутствовал → search гниёт). Fix: trigger_refresh_search_matview_run (по образцу asking_to_sold_ratio, через advisory-lock _claim_run #750, run_in_executor для REFRESH CONCURRENTLY с autocommit) + dispatch-branch + seed scrape_schedules (03:00–04:00 UTC ночь, до rosreestr-import; ON CONFLICT DO NOTHING).

Проверки

ruff clean. SQL — BEGIN/COMMIT, идемпотентны. Post-deploy QA: EXPLAIN deals street-query → Bitmap Index Scan; FDW remote-estimate; matview refresh по расписанию.

Отложено

E (#17 geocode city-centroid флаг) — нужна схема geo_precision + правка ST_DWithin radius-match (client-facing) → отдельный follow-up.

Refs #769

## Что Хвост #769 (A1+D смержены в #798; **E отложен** — geo-radius client-facing risk). Закрывает A2/B/C — все низкорисковые, не клиентские. ### A2 (#10, index) — `086_deals_address_trgm_index.sql` `deals.address` не имел GIN-trgm индекса → seq-scan на street-match. `pg_trgm` + `CREATE INDEX IF NOT EXISTS deals_address_trgm_idx ... gin(address gin_trgm_ops)`. Идемпот, plain `CREATE INDEX` (txn-safe). ### B (#13, FDW) — `087_fdw_server_options.sql` `gendesign_remote` без `fetch_size`/`use_remote_estimate` → плохое планирование 6.8M-row FDW import. `DO`-block читает `pg_foreign_server.srvoptions` → **ADD-or-SET** для каждой опции (идемпотентно при любом prior-state), `RAISE` если сервера нет. ### C (#14, matview) — `scheduler.py` + `088_*.sql` Находка: `listings_search_mv` **активно читается** `search_query.py` (`/api/v1/search`) но **никогда не рефрешился** (`refresh_search_matview.py` существует, в beat/scheduler отсутствовал → search гниёт). Fix: `trigger_refresh_search_matview_run` (по образцу `asking_to_sold_ratio`, через advisory-lock `_claim_run` #750, `run_in_executor` для `REFRESH CONCURRENTLY` с autocommit) + dispatch-branch + seed `scrape_schedules` (03:00–04:00 UTC ночь, до rosreestr-import; `ON CONFLICT DO NOTHING`). ## Проверки ruff clean. SQL — BEGIN/COMMIT, идемпотентны. Post-deploy QA: EXPLAIN deals street-query → Bitmap Index Scan; FDW remote-estimate; matview refresh по расписанию. ## Отложено **E** (#17 geocode city-centroid флаг) — нужна схема `geo_precision` + правка ST_DWithin radius-match (client-facing) → отдельный follow-up. Refs #769
bot-backend added 1 commit 2026-05-30 17:38:53 +00:00
Хвост #769 (A1+D смержены #798; E отложен — geo-radius client-risk).

A2 (#10 index): 086 — pg_trgm GIN индекс на deals.address (был seq-scan на
street-match). Идемпот (IF NOT EXISTS), plain CREATE INDEX (txn-safe).

B (#13 FDW): 087 — ALTER SERVER gendesign_remote OPTIONS fetch_size=10000 +
use_remote_estimate=true (лучше планируется 6.8M-row FDW import). DO-block
читает srvoptions → ADD-or-SET, идемпотентно.

C (#14 matview): listings_search_mv активно читается search_query.py но НИКОГДА
не рефрешился (refresh_search_matview.py существует, в beat/scheduler не было).
scheduler.py: + trigger_refresh_search_matview_run (по образцу asking_to_sold,
через _claim_run advisory-lock #750, run_in_executor — refresh CONCURRENTLY с
autocommit). 088 — seed scrape_schedules (03:00-04:00 UTC ночь, ON CONFLICT DO
NOTHING). ruff clean.

Post-deploy QA: EXPLAIN deals street-query → Bitmap Index Scan; FDW remote-estimate.
bot-reviewer approved these changes 2026-05-30 17:40:44 +00:00
bot-reviewer left a comment
Collaborator

APPROVE — data-layer tail #769 (A2+B+C), все три части низкорисковые и корректные.

Проверено:

  • scheduler.pytrigger_refresh_search_matview_run точно повторяет паттерн trigger_asking_to_sold_ratio_run (#648): _claim_runrun_in_executor для sync DB-op → mark_done/mark_failed через отдельную SessionLocal. Все хелперы существуют, callable refresh_search_matview() существует (app/tasks/refresh_search_matview.py:23), dispatch-branch добавлен без правки существующих веток.
  • 086 trgm — идемпотентно (IF NOT EXISTS), txn-safe (plain CREATE INDEX оправдан — deals наполняется батчами, стартует малой).
  • 087 FDW — DO-block ADD-or-SET против pg_foreign_server.srvoptions, идемпотентен при любом prior-state, RAISE если сервера нет.
  • 088 seed — ON CONFLICT (source) DO NOTHING, next_run_at на завтра 03:00 UTC (паттерн 078/079/082, не стреляет на деплое).

Anti-regression: estimator pricing/dedup не тронуты (#755/#753 соблюдены), self-extending файлы не затронуты, секретов нет.

Advisory (не блокер): task.add_done_callback(lambda t: t.exception() ...) — exception уже ловится внутри _run(), callback всегда вернёт None. Безвредный boilerplate.

Post-deploy QA (auto-qa): EXPLAIN deals street-query → Bitmap Index Scan; matview refresh по расписанию 03:00 UTC.

<!-- gendesign-review-bot: sha=dffe1cc verdict=approve --> ✅ **APPROVE** — data-layer tail #769 (A2+B+C), все три части низкорисковые и корректные. **Проверено:** - `scheduler.py` — `trigger_refresh_search_matview_run` точно повторяет паттерн `trigger_asking_to_sold_ratio_run` (#648): `_claim_run` → `run_in_executor` для sync DB-op → `mark_done/mark_failed` через отдельную `SessionLocal`. Все хелперы существуют, callable `refresh_search_matview()` существует (`app/tasks/refresh_search_matview.py:23`), dispatch-branch добавлен без правки существующих веток. - `086` trgm — идемпотентно (`IF NOT EXISTS`), txn-safe (plain CREATE INDEX оправдан — deals наполняется батчами, стартует малой). - `087` FDW — DO-block ADD-or-SET против `pg_foreign_server.srvoptions`, идемпотентен при любом prior-state, `RAISE` если сервера нет. - `088` seed — `ON CONFLICT (source) DO NOTHING`, `next_run_at` на завтра 03:00 UTC (паттерн 078/079/082, не стреляет на деплое). **Anti-regression:** estimator pricing/dedup не тронуты (#755/#753 соблюдены), self-extending файлы не затронуты, секретов нет. **Advisory (не блокер):** `task.add_done_callback(lambda t: t.exception() ...)` — exception уже ловится внутри `_run()`, callback всегда вернёт None. Безвредный boilerplate. Post-deploy QA (auto-qa): EXPLAIN deals street-query → Bitmap Index Scan; matview refresh по расписанию 03:00 UTC.
bot-reviewer merged commit a9e4aecb54 into main 2026-05-30 17:40:54 +00:00
bot-reviewer deleted branch fix/769-data-layer-a2b2c 2026-05-30 17:40:55 +00:00
Sign in to join this conversation.
No reviewers
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#804
No description provided.