Витрина сделок на лендинге МЕРЫ не пересчитывается: задачи нет в расписании, последний прогон 30.08 (13 суток назад), всего 3 прогона за всё вр… #3469

Closed
opened 2026-09-12 10:34:58 +00:00 by bot-backend · 2 comments
Collaborator

Найдено 12.09.2026 при работе над PR #3468 (полоса расхождения на витрине).

Факт

SELECT * FROM scrape_schedules WHERE source LIKE '%showcase%';   -- 0 строк
SELECT id, computed_at, considered, eligible, written FROM landing_showcase_runs ORDER BY id DESC;
  3 | 2026-08-30 08:48:52+00 | 200 | 159 | 20
  • В scrape_schedules нет строки для landing_showcase_deals — задача не запускается планировщиком вообще.
  • Прогонов за всё время три, последний — 2026-08-30, то есть витрина на публичном лендинге показывает данные тринадцатидневной давности и будет показывать их дальше, пока кто-нибудь не запустит задачу руками.

Почему это не видно

У страницы нет признака, по которому посетитель или владелец заметили бы, что данные заморожены: подпись под таблицей говорит про счётчики прогона (considered/eligible/written), но не про его ДАТУ. Свежесть соседних величин (/stats) считается ночной задачей и не отстаёт — из-за этого блок выглядит одинаково живым целиком.

Сравнить не с чем и по логам: маркера «витрина пересчитана» в мониторинге нет.

Чем это грозит прямо сейчас

PR #3468 вводит на витрину полосу расхождения −5…+20 % и говорит об этом на странице. Пока задача не перегнана, в таблице лежат строки прошлого правила (по замеру 12.09 — 12 из 20 вне полосы, от −27,87 % до +75,71 %). В самом PR это закрыто тем, что утверждение про полосу выводится из показанных данных, но корень — незапускаемая задача — остаётся.

Чинить

  1. Завести расписание (по образцу соседних задач в scrape_schedules) — частота по смыслу: сделки Росреестра приезжают поквартально, но сам расчёт МЕРЫ меняется с каждым деплоем, так что раз в сутки разумно.
  2. Показывать на странице дату прогона витрины рядом со счётчиками — чтобы «заморожено» было видно без похода в базу.
  3. Добавить витрину в монитор свежести (scrape_freshness_check), чтобы отсутствие прогона било тревогу так же, как у источников.

Приёмка

landing_showcase_runs пополняется без ручного запуска; на странице видна дата последнего пересчёта; отсутствие прогона дольше 3× такта даёт тревогу.

Refs PR #3468, #1948.

Найдено 12.09.2026 при работе над PR #3468 (полоса расхождения на витрине). ## Факт ```sql SELECT * FROM scrape_schedules WHERE source LIKE '%showcase%'; -- 0 строк SELECT id, computed_at, considered, eligible, written FROM landing_showcase_runs ORDER BY id DESC; 3 | 2026-08-30 08:48:52+00 | 200 | 159 | 20 ``` - В `scrape_schedules` **нет строки** для `landing_showcase_deals` — задача не запускается планировщиком вообще. - Прогонов за всё время **три**, последний — **2026-08-30**, то есть витрина на публичном лендинге показывает данные тринадцатидневной давности и будет показывать их дальше, пока кто-нибудь не запустит задачу руками. ## Почему это не видно У страницы нет признака, по которому посетитель или владелец заметили бы, что данные заморожены: подпись под таблицей говорит про счётчики прогона (`considered/eligible/written`), но не про его ДАТУ. Свежесть соседних величин (`/stats`) считается ночной задачей и не отстаёт — из-за этого блок выглядит одинаково живым целиком. Сравнить не с чем и по логам: маркера «витрина пересчитана» в мониторинге нет. ## Чем это грозит прямо сейчас PR #3468 вводит на витрину полосу расхождения −5…+20 % и говорит об этом на странице. Пока задача не перегнана, в таблице лежат строки прошлого правила (по замеру 12.09 — 12 из 20 вне полосы, от −27,87 % до +75,71 %). В самом PR это закрыто тем, что утверждение про полосу выводится из показанных данных, но корень — незапускаемая задача — остаётся. ## Чинить 1. Завести расписание (по образцу соседних задач в `scrape_schedules`) — частота по смыслу: сделки Росреестра приезжают поквартально, но сам расчёт МЕРЫ меняется с каждым деплоем, так что раз в сутки разумно. 2. Показывать на странице дату прогона витрины рядом со счётчиками — чтобы «заморожено» было видно без похода в базу. 3. Добавить витрину в монитор свежести (`scrape_freshness_check`), чтобы отсутствие прогона било тревогу так же, как у источников. ## Приёмка `landing_showcase_runs` пополняется без ручного запуска; на странице видна дата последнего пересчёта; отсутствие прогона дольше 3× такта даёт тревогу. Refs PR #3468, #1948.
Author
Collaborator

Поправка к моему же тексту: «три прогона за всё время» — неверно

В теле issue я написал: «Прогонов за всё время три». Это ошибка чтения. Проверил по коду:

_DELETE_RUNS_SQL = text("DELETE FROM landing_showcase_runs")   # app/tasks/landing_showcase_deals.py:369
...
db.execute(_DELETE_SQL)        # :528
db.execute(_DELETE_RUNS_SQL)   # :529

Каждый прогон стирает предыдущие и пишет одну строку. То есть id = 3 — это значение последовательности, а не число прогонов; сколько их было на самом деле, из этой таблицы не узнать вовсе. Сейчас в таблице одна строка, id = 4.

Что из этого НЕ меняется: расписания у задачи нет (scrape_schedules → 0 строк, подтверждено повторно), автоматических прогонов не было, и на момент заведения issue витрина показывала данные от 30.08, то есть тринадцатисуточной давности. Корень и приёмка в силе.

Что меняется: «три прогона» из формулировки убираю — обосновывать редкость пересчёта этим числом нельзя.

Побочно: то, что таблица не хранит историю прогонов, — отдельная мелочь. Она означает, что по ней нельзя ответить «как часто витрина пересчитывалась» даже после появления расписания. Если эта величина понадобится, историю надо хранить, а не восстанавливать по последовательности id.

Ещё одна поправка: корень был двойной

Правка нашла вторую половину, которой в issue нет: в app/services/product_handlers.py не было обработчика landing_showcase_deals. Одной строки в scrape_schedules не хватило бы — планировщик заклеймил бы прогон и не нашёл, чем его выполнить. Обе половины едут в PR #3509.

## Поправка к моему же тексту: «три прогона за всё время» — неверно В теле issue я написал: «Прогонов за всё время **три**». Это ошибка чтения. Проверил по коду: ```python _DELETE_RUNS_SQL = text("DELETE FROM landing_showcase_runs") # app/tasks/landing_showcase_deals.py:369 ... db.execute(_DELETE_SQL) # :528 db.execute(_DELETE_RUNS_SQL) # :529 ``` Каждый прогон **стирает предыдущие** и пишет одну строку. То есть `id = 3` — это значение последовательности, а не число прогонов; сколько их было на самом деле, из этой таблицы не узнать вовсе. Сейчас в таблице одна строка, `id = 4`. **Что из этого НЕ меняется:** расписания у задачи нет (`scrape_schedules` → 0 строк, подтверждено повторно), автоматических прогонов не было, и на момент заведения issue витрина показывала данные от 30.08, то есть тринадцатисуточной давности. Корень и приёмка в силе. **Что меняется:** «три прогона» из формулировки убираю — обосновывать редкость пересчёта этим числом нельзя. Побочно: то, что таблица не хранит историю прогонов, — отдельная мелочь. Она означает, что по ней нельзя ответить «как часто витрина пересчитывалась» даже после появления расписания. Если эта величина понадобится, историю надо хранить, а не восстанавливать по последовательности id. ## Ещё одна поправка: корень был двойной Правка нашла вторую половину, которой в issue нет: в `app/services/product_handlers.py` **не было обработчика** `landing_showcase_deals`. Одной строки в `scrape_schedules` не хватило бы — планировщик заклеймил бы прогон и не нашёл, чем его выполнить. Обе половины едут в PR #3509.
Author
Collaborator

Приёмка на проде — 2026-09-12

PR #3509 смержен, доезд проверен по фактам, а не по статусам:

_schema_migrations LIKE '303_%'  = 1
scrape_schedules: landing_showcase_deals enabled=true окно 6-7 next=2026-09-13 06:00 (UTC)
product_handlers.py:942  "landing_showcase_deals": Handler(_job_landing_showcase_deals, …)

next_run_at стоит на завтра намеренно — чтобы задача не стартовала в момент деплоя. Обе половины корня закрыты: и строка расписания, и обработчик (без второго расписание молчало бы вечно — планировщик клеймил бы прогон и не находил, чем его выполнять).

Что проверить завтра

После 2026-09-13 06:00 UTC:

SELECT id, computed_at FROM landing_showcase_runs;                    -- новый прогон
SELECT status, counters FROM scrape_runs
 WHERE source='landing_showcase_deals' ORDER BY id DESC LIMIT 3;      -- и как он прошёл

плюс на странице meraocenka.ru — подпись «Витрина пересчитана …» с новой датой (учитывая, что фетч витрины кэшируется на час).

Оговорка, вынесенная отдельно

Прогон с нулём строк завершится успехом, погасит часы свежести и снимет со страницы весь блок вместе с новой датой — см. #3511. С суточным расписанием это становится ежесуточной возможностью, поэтому чинить стоит до того, как оно случится само.

## Приёмка на проде — 2026-09-12 PR #3509 смержен, доезд проверен по фактам, а не по статусам: ``` _schema_migrations LIKE '303_%' = 1 scrape_schedules: landing_showcase_deals enabled=true окно 6-7 next=2026-09-13 06:00 (UTC) product_handlers.py:942 "landing_showcase_deals": Handler(_job_landing_showcase_deals, …) ``` `next_run_at` стоит на завтра намеренно — чтобы задача не стартовала в момент деплоя. Обе половины корня закрыты: и строка расписания, и обработчик (без второго расписание молчало бы вечно — планировщик клеймил бы прогон и не находил, чем его выполнять). ## Что проверить завтра После 2026-09-13 06:00 UTC: ```sql SELECT id, computed_at FROM landing_showcase_runs; -- новый прогон SELECT status, counters FROM scrape_runs WHERE source='landing_showcase_deals' ORDER BY id DESC LIMIT 3; -- и как он прошёл ``` плюс на странице `meraocenka.ru` — подпись «Витрина пересчитана …» с новой датой (учитывая, что фетч витрины кэшируется на час). ## Оговорка, вынесенная отдельно Прогон с нулём строк завершится успехом, погасит часы свежести и снимет со страницы весь блок вместе с новой датой — см. #3511. С суточным расписанием это становится ежесуточной возможностью, поэтому чинить стоит до того, как оно случится само.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3469
No description provided.