From dba508f5ce9e721a6641ee31c0a13980c643d686 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Thu, 17 Sep 2026 08:50:04 +0300 Subject: [PATCH] =?UTF-8?q?fix(trade-in):=20=D1=80=D0=B0=D0=B7=D0=B2=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B8=20=D0=BE=D0=BA=D0=BD=D0=B0=20=D0=94=D0=BE?= =?UTF-8?q?=D0=BC=D0=9A=D0=BB=D0=B8=D0=BA=D0=B0=20=E2=80=94=20=D0=BE=D0=B1?= =?UTF-8?q?=D0=BB=D0=B0=D1=81=D1=82=D1=8C=20=D0=BD=D0=B5=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=BB=D0=B6=D0=BD=D0=B0=20=D1=81=D1=82=D0=B0=D1=80=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D1=8C=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=B5?= =?UTF-8?q?=20=D1=81=20=D0=95=D0=9A=D0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Миграция 306 поставила domclick_city_sweep_moskovskaya_oblast в окно 3-6 — ровно то же, где сидит ЕКБ-строка domclick_city_sweep. Планировщик домклик-джобы не сериализует: 17.09 обе новые строки заклеймлены в одну секунду (run 7333 и 7334, 05:00:55) и пошли параллельно. Два свипа ДомКлика делят один браузерный сайдкар и один пул. В минуты параллельного прогона tradein-browser держал 67% CPU, 1.67 из 2.5 ГиБ и 2297 PID, часть запросов возвращалась как Page.goto Timeout 60000ms и socket hang up. Узлов с provider_affinity='any' всего два (id 13, 14), их же берёт cian. Миграция НЕ утверждает, что параллельность уронила сбор: померить это по ходу прогона нечем — fetch_city копит лоты в память и сохраняет одним save_listings после всех шести бакетов, так что ноль строк в listings в середине прогона — норма (здоровый одиночный ЕКБ-свип 16.09, run 7219, тоже молчал 70 минут и затем положил 6372/237). Окна разводятся по ресурсной причине, а не по этой метрике. Область → 9-12: там нет ни одной домклик-строки. Москва остаётся в 0-3. next_run_at выставлен явно и разнесён — иначе сохранились бы значения первого клейма (область 20.09 04:11, внутри ЕКБ-окна) и коллизия повторилась бы. Проверено сухим прогоном на проде под ROLLBACK: UPDATE 1 + UPDATE 1, итоговые окна 3-6 (ЕКБ) / 0-3 Москва 20.09 00:30 / 9-12 область 20.09 09:30. Claude-Session: https://claude.ai/code/session_01NQb6WeJtagZwZnUsSjDizs --- .../307_domclick_msk_window_no_collision.sql | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tradein-mvp/backend/data/sql/307_domclick_msk_window_no_collision.sql diff --git a/tradein-mvp/backend/data/sql/307_domclick_msk_window_no_collision.sql b/tradein-mvp/backend/data/sql/307_domclick_msk_window_no_collision.sql new file mode 100644 index 00000000..4a7178bd --- /dev/null +++ b/tradein-mvp/backend/data/sql/307_domclick_msk_window_no_collision.sql @@ -0,0 +1,60 @@ +-- 307_domclick_msk_window_no_collision.sql +-- Развести окна ДомКлика: областной свип не должен стартовать вместе с ЕКБ-свипом. +-- +-- Apply after: 306_scrape_schedules_seed_domclick_msk.sql +-- +-- WHY: +-- Миграция 306 поставила 'domclick_city_sweep_moskovskaya_oblast' в окно 3-6 — РОВНО +-- то же, где с самого начала сидит ЕКБ-строка 'domclick_city_sweep'. Планировщик +-- домклик-джобы не сериализует: 17.09.2026 обе новые строки были заклеймлены в одну +-- секунду (run_id 7333 и 7334, 05:00:55) и пошли параллельно. +-- +-- Почему это плохо, без домыслов о причинности: два свипа ДомКлика делят ОДИН +-- браузерный сайдкар и ОДИН пул. В минуты параллельного прогона tradein-browser +-- держал 67% CPU, 1.67 из 2.5 ГиБ и 2297 PID, а часть запросов возвращалась как +-- 'Page.goto: Timeout 60000ms' и 'socket hang up' → HTTP 500. Узлов с +-- provider_affinity='any' в пуле всего два (id 13 и 14) — их же берёт cian, так что +-- параллельная пара домклик-свипов забирает оба. +-- +-- ЧЕГО ЭТА МИГРАЦИЯ НЕ УТВЕРЖДАЕТ: что параллельность уронила сбор. Померить это по +-- ходу прогона нечем — DomClickScraper.fetch_city копит лоты в память и сохраняет их +-- ОДНИМ save_listings после обхода всех шести бакетов, инкрементального сохранения +-- нет. Поэтому 'ноль строк в listings за 45 минут' — нормальное состояние середины +-- прогона (здоровый одиночный ЕКБ-свип 16.09, run 7219, тоже не писал ничего 70 минут +-- и затем положил 6372 seen / 237 new). Разводим окна по ресурсной причине выше, а не +-- по выводу из этой метрики. +-- +-- Новое окно области — 9-12: там нет НИ ОДНОЙ домклик-строки (домклик-джобы всего +-- три: 'domclick_city_sweep' 3-6, 'domclick_city_sweep_moskva' 0-3 и +-- 'domclick_detail_backfill' 15-18). Москва остаётся в 0-3 — она и так единственный +-- домклик в этом окне. +-- +-- next_run_at выставляется ЯВНО и разнесён: без этого строки сохранили бы значения, +-- посчитанные при первом клейме (Москва 20.09 01:46, область 20.09 04:11), а 04:11 +-- попадает внутрь ЕКБ-окна 3-6 — та же коллизия повторилась бы через трое суток. +-- +-- Скобки + 'AT TIME ZONE UTC' на РЕЗУЛЬТАТЕ, а не только внутри: next_run_at — +-- timestamptz, а date_trunc от naive-времени вернул бы timestamp без зоны, и приведение +-- поехало бы по таймзоне сессии. Здесь обе стороны явные. +-- +-- ИДЕМПОТЕНТНОСТЬ: UPDATE ... WHERE source = '...' — повторный прогон переписывает те +-- же значения. enabled НЕ трогаем: если строку выключили вручную, она останется +-- выключенной. + +BEGIN; + +SET LOCAL lock_timeout = '5s'; + +UPDATE scrape_schedules + SET window_start_hour = 9, + window_end_hour = 12, + next_run_at = (date_trunc('day', now() AT TIME ZONE 'UTC') + + interval '3 days 9 hours 30 minutes') AT TIME ZONE 'UTC' + WHERE source = 'domclick_city_sweep_moskovskaya_oblast'; + +UPDATE scrape_schedules + SET next_run_at = (date_trunc('day', now() AT TIME ZONE 'UTC') + + interval '3 days 0 hours 30 minutes') AT TIME ZONE 'UTC' + WHERE source = 'domclick_city_sweep_moskva'; + +COMMIT; -- 2.45.3