fix(tradein/scrapers): метка наблюдения — время строки, а не старта транзакции (#2731) #2742

Merged
bot-backend merged 1 commit from fix/2731-clock-timestamp-content into main 2026-08-06 16:19:57 +00:00

1 commit

Author SHA1 Message Date
54714f0aa2 fix(tradein/scrapers): метка наблюдения — время строки, а не старта транзакции (#2731)
All checks were successful
CI / changes (pull_request) Successful in 13s
CI Trade-In / changes (pull_request) Successful in 13s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
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 3m36s
save_listings и upsert_listing_snapshot писали observed_at/scraped_at/last_seen_at
через NOW() == transaction_timestamp(). Коммит у писателя один, в конце всего batch'а,
поэтому все строки вызова несли одну метку: прод 2026-08-06 — run 3303 219 строк на
1 метку при семи минутах работы, run 3229 2643 строки на 55 меток (метка на вызов
save_listings, не на строку).

Цена — не фильтры свежести: смещение равно длительности прогона (минуты; худший
случай 17.3 ч у cian_full_load) против окна в 14 суток, то есть 0.03-5%. Теряется
разрешение во времени — темп сбора и порядок строк внутри прогона по данным не
восстановить, отсюда же следовала невозможность бэкфилла run_id (#2701).

statement_timestamp(), а НЕ clock_timestamp() как в #2702/#2718: здесь одним
statement'ом пишутся ДВЕ колонки, обязанные совпадать (после #2206 scraped_at =
last_seen_at у 100% строк, на этом равенстве стоит предикат миграции 161).
Прод-проверка: clock_timestamp() = clock_timestamp() → false, а
statement_timestamp() = statement_timestamp() → true; при этом statement_timestamp()
двигается от запроса к запросу внутри одной транзакции, а каждый upsert — свой запрос.

Set-based писатели (listing_source_snapshots 89827 строк одним statement'ом,
deactivate_stale_avito) намеренно НЕ тронуты: там одна метка — правда о statement'е,
а clock_timestamp() дал бы ложное разрешение (прод: 27783 разных значения на 200000
строк одного statement'а, кодирующих порядок обработки, а не наблюдения).

Миграция 232 — только COMMENT ON COLUMN: фиксирует дату перехода и то, что
исторические строки невосстановимы (внутрипрогонное время нигде не сохранялось).

Refs #2731
2026-08-06 21:12:17 +05:00