fix(analytics): address review-bot PR B fixes (#113)
SQL (data/sql/94_mv_layout_velocity.sql): - 🟠 idempotency WARN comment перед DROP CASCADE - 🟡 WITH NO DATA + REFRESH after CREATE INDEX (меньше lock duration) - 🟡 WHERE cm.objective_group = 'Екатеринбург' (cross-region Cartesian защита) - 🟡 COMMENT ON MATERIALIZED VIEW с источниками + refresh механизмом Python (services/site_finder/layout_velocity_refresh.py): - 🟡 db.commit() после REFRESH (visibility через connection pool) - 🟡 убрать f-string в SQL — две явных text() ветки - 🟡 try/except OperationalError fallback на non-concurrent
This commit is contained in:
parent
144970aadd
commit
46c2a84ea4
2 changed files with 36 additions and 3 deletions
|
|
@ -16,6 +16,7 @@ from __future__ import annotations
|
|||
import logging
|
||||
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.exc import OperationalError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -34,8 +35,22 @@ def refresh_layout_velocity(db: Session, *, concurrently: bool = True) -> int:
|
|||
Returns:
|
||||
Row count in the MV after refresh (for observability / alerting).
|
||||
"""
|
||||
mode = "CONCURRENTLY" if concurrently else ""
|
||||
db.execute(text(f"REFRESH MATERIALIZED VIEW {mode} mv_layout_velocity"))
|
||||
try:
|
||||
if concurrently:
|
||||
db.execute(text("REFRESH MATERIALIZED VIEW CONCURRENTLY mv_layout_velocity"))
|
||||
else:
|
||||
db.execute(text("REFRESH MATERIALIZED VIEW mv_layout_velocity"))
|
||||
db.commit()
|
||||
except OperationalError as e:
|
||||
if concurrently and "cannot refresh materialized view" in str(e).lower():
|
||||
logger.warning(
|
||||
"CONCURRENTLY failed (MV likely not populated), falling back to non-concurrent"
|
||||
)
|
||||
db.rollback()
|
||||
db.execute(text("REFRESH MATERIALIZED VIEW mv_layout_velocity"))
|
||||
db.commit()
|
||||
else:
|
||||
raise
|
||||
row = db.execute(text("SELECT COUNT(*) FROM mv_layout_velocity")).first()
|
||||
count = int(row[0]) if row else 0
|
||||
logger.info("mv_layout_velocity refreshed: %d rows", count)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,13 @@
|
|||
--
|
||||
-- Deploy: auto-applied by deploy.yml via _schema_migrations tracking.
|
||||
-- Dependencies: none (no views depend on this MV at creation time).
|
||||
--
|
||||
-- WARN: Re-apply этого файла (DR / lost _schema_migrations entry / dev local)
|
||||
-- снесёт MV + CASCADE удалит зависимости (e.g. future /best-layouts views).
|
||||
-- После re-apply ПЕРВЫЙ refresh должен быть concurrently=False
|
||||
-- (CONCURRENTLY требует уже populated MV — упадёт на пустой).
|
||||
-- Tracking table `_schema_migrations` нормально предотвращает re-apply,
|
||||
-- но добавлен comment как safety reminder.
|
||||
|
||||
BEGIN;
|
||||
|
||||
|
|
@ -59,9 +66,12 @@ JOIN objective_complex_mapping cm
|
|||
ON cm.objective_complex_name = l.project_name
|
||||
WHERE l.room_bucket IS NOT NULL
|
||||
AND cm.domrf_obj_id IS NOT NULL
|
||||
GROUP BY cm.domrf_obj_id, l.room_bucket;
|
||||
AND cm.objective_group = 'Екатеринбург' -- защита от cross-region Cartesian при future multi-city
|
||||
GROUP BY cm.domrf_obj_id, l.room_bucket
|
||||
WITH NO DATA;
|
||||
|
||||
-- UNIQUE index required for REFRESH CONCURRENTLY (future periodic refreshes)
|
||||
-- Created on empty MV → instant, no lock duration on data
|
||||
CREATE UNIQUE INDEX mv_layout_velocity_pk
|
||||
ON mv_layout_velocity (obj_id, room_bucket);
|
||||
|
||||
|
|
@ -69,4 +79,12 @@ CREATE UNIQUE INDEX mv_layout_velocity_pk
|
|||
CREATE INDEX mv_layout_velocity_obj_idx
|
||||
ON mv_layout_velocity (obj_id);
|
||||
|
||||
-- Initial populate (non-concurrent — MV was just created, CONCURRENTLY not allowed on empty MV)
|
||||
REFRESH MATERIALIZED VIEW mv_layout_velocity;
|
||||
|
||||
COMMENT ON MATERIALIZED VIEW mv_layout_velocity IS
|
||||
'Per-(obj_id, room_bucket) deals aggregation за last 24 months. '
|
||||
'Source: objective_corpus_room_month × objective_complex_mapping (EKB only). '
|
||||
'Refresh via layout_velocity_refresh.py (concurrently=True after initial populate).';
|
||||
|
||||
COMMIT;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue