All checks were successful
CI Trade-In / changes (pull_request) Successful in 11s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 13s
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 4m54s
Обе миграции создавали индекс без транзакции и без SET LOCAL lock_timeout. Гейт scripts/check-migration-lock-timeout.py это и поймал: ::error 276_landing_showcase_deals.sql:: блокирующий DDL без lock_timeout (CREATE INDEX IF NOT EXISTS idx_landing_showcase_deals_computed_at ...) Обе обёрнуты в BEGIN + SET LOCAL lock_timeout = '5s' + COMMIT по образцу 272_houses_region_code.sql. Локально гейт зелёный: «проверено новых миграций: 31».
44 lines
2.9 KiB
PL/PgSQL
44 lines
2.9 KiB
PL/PgSQL
-- 277: итог пересчёта витрины лэндинга — счётчики рядом со строками.
|
||
--
|
||
-- ЗАЧЕМ ОТДЕЛЬНАЯ ТАБЛИЦА, А НЕ КОЛОНКИ В landing_showcase_deals. Счётчики —
|
||
-- факт ПРОГОНА, а не строки: на 20 строк они были бы продублированы 20 раз, а
|
||
-- в самом важном случае — когда показывать оказалось нечего — исчезли бы
|
||
-- вместе со строками. «Рассмотрено 200, показывать нечего» обязано доезжать до
|
||
-- фронта ровно так же, как «рассмотрено 200, показано 20».
|
||
--
|
||
-- ЗАЧЕМ ВООБЩЕ. Витрина показывает 20 сделок «МЕРА сказала X — продали за Y».
|
||
-- Без чисел рядом эти 20 строк читаются как «столько и было»: посетитель не
|
||
-- может отличить выборку из работы оценщика от её лучшего хвоста. Поэтому
|
||
-- ручка /api/public/mera/showcase отдаёт вместе со строками, сколько сделок
|
||
-- рассмотрено, сколько годных строк не поместилось и по какому правилу
|
||
-- отбраковано остальное.
|
||
--
|
||
-- rejection_rule — ТЕКСТ, А НЕ КОД ПРАВИЛА. Правило живёт в
|
||
-- app/tasks/landing_showcase_deals.REJECTION_RULE и пишется сюда тем прогоном,
|
||
-- который эти числа и посчитал: подпись под витриной обязана описывать ТОТ
|
||
-- отбор, что дал эти строки, а не тот, что задеплоен сегодня.
|
||
--
|
||
-- computed_at совпадает со строками батча: задача пишет строки и этот итог
|
||
-- ОДНОЙ транзакцией, а now() в Postgres — время начала транзакции.
|
||
BEGIN;
|
||
-- Конвенция проекта (#2752): блокирующий DDL идёт под lock_timeout, иначе он
|
||
-- встанет в очередь за чужой сессией и утащит за собой запросы приложения.
|
||
SET LOCAL lock_timeout = '5s';
|
||
|
||
CREATE TABLE IF NOT EXISTS landing_showcase_runs (
|
||
id bigserial PRIMARY KEY,
|
||
computed_at timestamptz NOT NULL DEFAULT now(),
|
||
considered integer NOT NULL,
|
||
priced integer NOT NULL,
|
||
no_prediction integer NOT NULL,
|
||
incomplete integer NOT NULL,
|
||
eligible integer NOT NULL,
|
||
written integer NOT NULL,
|
||
with_district integer NOT NULL,
|
||
rejection_rule text NOT NULL
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_landing_showcase_runs_computed_at
|
||
ON landing_showcase_runs (computed_at DESC);
|
||
|
||
COMMIT;
|