From d4c5cb84c40ca8da1c1655fde8e268517fb3badc Mon Sep 17 00:00:00 2001 From: bot-backend Date: Thu, 6 Aug 2026 16:21:17 +0500 Subject: [PATCH] =?UTF-8?q?chore(tradein/db):=20DROP=20listings=5Fsnapshot?= =?UTF-8?q?s.position=5Fin=5Fserp=20=E2=80=94=20=D1=88=D0=B0=D0=B3=202=20?= =?UTF-8?q?=D0=B8=D0=B7=202=20(#2697)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Колонка признана невыразимой в этой таблице (#2674, диагноз в миграции 217): позиция есть свойство пары «объявление × конкретный прогон выдачи с конкретными фильтрами», а PRIMARY KEY (listing_id, snapshot_date) держит одну строку на объявление в сутки — за 2026-08-03 по этому ключу писали 13 разных run_id и четыре SERP-источника. Шаг 1 (правка писателя) уже на проде, поэтому окна «SQL применяется до перезапуска контейнеров» больше нет. Предусловие проверено по коду В КОНТЕЙНЕРАХ, а не по зелёному деплою: grep по /app в tradein-scraper и tradein-backend находит имя колонки ровно в четырёх строках docstring'а snapshot_writer.py и ни в одном SQL; сигнатура upsert_listing_snapshot колонку не содержит; второй писатель (deactivate_stale_avito._STALE_SNAPSHOT_TAIL) перечисляет колонки явно и этой в списке не имеет. Читателей нет: 0 непустых значений из 397 217 строк на проде, 0 зависимых view/matview (pg_depend → pg_rewrite), ни индексов, ни триггеров, ни foreign table над таблицей; в коде нет ни одного SELECT-читателя (SELECT * по таблице отсутствует), фронт, экспортёры и админка колонку не упоминают. Refs #2697 --- .../data/sql/227_drop_position_in_serp.sql | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tradein-mvp/backend/data/sql/227_drop_position_in_serp.sql diff --git a/tradein-mvp/backend/data/sql/227_drop_position_in_serp.sql b/tradein-mvp/backend/data/sql/227_drop_position_in_serp.sql new file mode 100644 index 00000000..8f9e2a8a --- /dev/null +++ b/tradein-mvp/backend/data/sql/227_drop_position_in_serp.sql @@ -0,0 +1,41 @@ +-- 227_drop_position_in_serp.sql +-- listings_snapshots.position_in_serp — DROP, шаг 2 из 2 (#2697, продолжение #2674). +-- +-- Dependencies: 217_position_in_serp_unexpressible.sql (диагноз + COMMENT на колонке). +-- Apply after: 224_houses_house_type_canon.sql +-- Идемпотентно: DROP COLUMN IF EXISTS. +-- +-- ── ПОЧЕМУ УДАЛЯЕМ, А НЕ ПОДКЛЮЧАЕМ ────────────────────────────────────────── +-- Полный разбор — в 217. Кратко: позиция есть свойство пары (объявление, конкретный +-- прогон выдачи с конкретными фильтрами), а PRIMARY KEY (listing_id, snapshot_date) +-- держит одну строку на объявление в сутки — при том что за 2026-08-03 по этому ключу +-- писали 13 разных run_id и четыре SERP-источника, а внутри одного city_sweep +-- объявление приезжает с разным индексом от перекрывающихся гео-якорей. Значение +-- оседало бы от последнего писателя дня и читалось бы как факт. Честное хранение — +-- отдельная таблица с ключом (run_id, listing_id) и сохранёнными фильтрами прогона, +-- то есть НЕ возврат этой колонки. +-- +-- ── ПРЕДУСЛОВИЕ ПРОВЕРЕНО ПЕРЕД МЕРЖЕМ (2026-08-06) ────────────────────────── +-- Окно «SQL применяется ДО перезапуска контейнеров» закрыто тем, что правка кода +-- (#2694) уже живёт на проде — проверено ПО КОДУ В КОНТЕЙНЕРАХ, не по зелёному +-- деплою: grep по /app в tradein-scraper и tradein-backend находит имя колонки +-- ровно в четырёх строках docstring'а snapshot_writer.py (18/34/37/76) и ни в одном +-- SQL; inspect.signature(upsert_listing_snapshot) колонку не содержит. +-- Оба живых писателя перечисляют колонки явно и этой в списке не имеют: +-- * scraper_kit/snapshot_writer.py::upsert_listing_snapshot (весь скрейп-путь), +-- * app/tasks/deactivate_stale_avito.py::_STALE_SNAPSHOT_TAIL (TTL-снимки 'stale'). +-- +-- ── ЧИТАТЕЛЕЙ НЕТ ──────────────────────────────────────────────────────────── +-- На проде: 0 непустых значений из 397 217 строк; 0 view/matview зависят от колонки +-- (pg_depend → pg_rewrite); индексов и триггеров на ней нет; foreign table над +-- listings_snapshots не существует (FDW-обёртки только над gendesign-таблицами); +-- в information_schema.columns имя встречается ровно в этой таблице. В коде: ни +-- одного SELECT-читателя (`SELECT *` по таблице нигде нет), фронт/экспортёры/админка +-- колонку не упоминают. Единственный сторож — tests/test_snapshot_writer.py, он +-- проверяет отсутствие колонки у писателя и после DROP остаётся валиден. + +BEGIN; + +ALTER TABLE listings_snapshots DROP COLUMN IF EXISTS position_in_serp; + +COMMIT;