From 03926a5d0b655cdf2c2ce1a0f59e908781a870f9 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Thu, 20 Aug 2026 14:56:37 +0500 Subject: [PATCH] =?UTF-8?q?fix(ptica):=20lock=5Ftimeout=20=D0=B2=20=D0=BC?= =?UTF-8?q?=D0=B8=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20189=20+=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B7=D0=B1=D0=BE=D1=80=20SQL=20=D0=B2=20=D1=80=D0=B5?= =?UTF-8?q?=D0=BF=D0=B5=D1=82=D0=B8=D1=86=D0=B8=D0=B8=20(#2464)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Гейт репозитория поймал упущение: блокирующий DDL без lock_timeout (#2752). Без него ALTER TABLE встаёт в очередь за чужой сессией и уводит за собой запросы приложения. Добавлен `SET LOCAL lock_timeout = '5s'` первой строкой после BEGIN. Пять секунд — про ОЖИДАНИЕ блокировки, не про работу: таблица 297 строк, сам DDL мгновенный. Не дождались — миграция падает, а не подвешивает прод. Заодно переписан разбор миграции в тесте-репетиции. Он дважды подвёл на мне же: 1) пропускал куски, начинающиеся с «--» → терялся DELETE, репетиция падала на ADD CONSTRAINT; 2) резал SQL по «;», встреченной ВНУТРИ текста комментария. Теперь комментарии снимаются ДО разбиения на выражения — оба класса закрыты. Прогон: tests/sql/test_2464_land_reservation_dedup.py — 6 passed rc=0. Co-Authored-By: Claude Opus 5 --- .../sql/test_2464_land_reservation_dedup.py | 18 +++++++++--------- ...189_land_reservation_nulls_not_distinct.sql | 6 ++++++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/backend/tests/sql/test_2464_land_reservation_dedup.py b/backend/tests/sql/test_2464_land_reservation_dedup.py index 3fe92c2d..f9e923ee 100644 --- a/backend/tests/sql/test_2464_land_reservation_dedup.py +++ b/backend/tests/sql/test_2464_land_reservation_dedup.py @@ -190,15 +190,15 @@ def test_migration_body_runs_on_a_prod_shaped_replica(db) -> None: sql = _MIGRATION.read_text() body = sql[sql.index("BEGIN;") + len("BEGIN;") : sql.rindex("COMMIT;")] - for chunk in body.split(";"): - # Срезаем ведущие строки-комментарии, а не пропускаем кусок целиком: - # DELETE в миграции идёт СРАЗУ ПОСЛЕ комментария, и наивный пропуск - # «кусков, начинающихся с --» молча выкинул бы его. Первая версия этого - # теста так и сделала — репетиция упала на ADD CONSTRAINT, и это было - # ровно то, что она и должна ловить. - stmt = "\n".join( - ln for ln in chunk.splitlines() if ln.strip() and not ln.lstrip().startswith("--") - ).strip() + # Комментарии снимаем ДО разбиения на выражения — иначе точка с запятой внутри + # комментария разрежет SQL посередине. Обе ловушки этот тест уже ловил на себе: + # сперва пропуск куска, начинающегося с «--» (потерялся DELETE, репетиция упала + # на ADD CONSTRAINT), затем «;» в тексте комментария. + code = "\n".join( + ln for ln in body.splitlines() if ln.strip() and not ln.lstrip().startswith("--") + ) + for chunk in code.split(";"): + stmt = chunk.strip() if stmt: db.execute(text(stmt)) diff --git a/data/sql/189_land_reservation_nulls_not_distinct.sql b/data/sql/189_land_reservation_nulls_not_distinct.sql index 3f08ed91..1701fe91 100644 --- a/data/sql/189_land_reservation_nulls_not_distinct.sql +++ b/data/sql/189_land_reservation_nulls_not_distinct.sql @@ -33,6 +33,12 @@ BEGIN; +-- #2752: блокирующий DDL обязан иметь lock_timeout — иначе ALTER TABLE встанет в +-- очередь за чужой сессией и уведёт за собой запросы приложения. Таблица крошечная +-- (297 строк), сам DDL мгновенный; пять секунд — про ОЖИДАНИЕ блокировки, не про +-- работу. Не дождались — миграция падает, а не подвешивает прод. +SET LOCAL lock_timeout = '5s'; + -- 1) Дедуп: оставляем строку с минимальным id в каждой группе. DELETE FROM land_reservation a USING land_reservation b