fix(generator): устранён флаки runtime-гейта стыка backfill/live
- Зачем:
- гейт generated-history-runtime-check падал через раз: docker compose
stop убивал генератор SIGKILL'ом посреди batch (SIGTERM не ловился),
непарные строки маскировались под «смену фактуры» (задача 20).
- Что:
- генератор грациозно завершается по SIGTERM: текущий batch дописывается
во все топики с flush и записью history; compose даёт минуту grace.
- runtime-check ждёт пересекающий визит в STG (предусловие проверки),
seam-check получил precheck непарных live-строк; в STG-запросах
закреплён 'UTC' против сдвига наивных меток в поясе сервера.
- контрактные тесты усилены, задача 20 закрыта, блокер задачи 13 снят.
- Проверка:
- тесты: 192 passed (generator), 21 passed (контракты);
- стенд: 3 подряд зелёных make generated-history-runtime-check;
красный сценарий (искажение referer_url пересекающего визита) валит
гейт прежним сообщением при нулевых непарных счётчиках.
This commit is contained in:
+3
-2
@@ -81,8 +81,9 @@ Status: ready-for-agent
|
||||
|
||||
## Blocked by
|
||||
|
||||
- `20-flaky-runtime-seam-check.md` — доверенный стабильный гейт стыка нужен
|
||||
до навешивания на него цепочки границ; фикс 20 идёт первым.
|
||||
- Нет. Последний блокер снят 2026-07-12: `20-flaky-runtime-seam-check.md`
|
||||
закрыта, гейт стыка стабилен (3 подряд зелёных прогона, красный сценарий
|
||||
ловится).
|
||||
- Исторические блокеры закрыты: `15-world-boundary-after-cross-review.md`
|
||||
(граница миров) и `17-trusted-checks-startup-history-superset.md`
|
||||
(доверенные проверки) — done.
|
||||
|
||||
+42
-12
@@ -1,4 +1,4 @@
|
||||
Status: ready-for-agent
|
||||
Status: done
|
||||
|
||||
# Runtime-проверка стыка нестабильна: фактура меняется через раз
|
||||
|
||||
@@ -99,24 +99,54 @@ location/device/geo -> DDS строит `dds.event` через `LEFT JOIN locati
|
||||
сужение окна `GEN_LIVE_CHECK_MINUTES` и прочие способы снизить
|
||||
вероятность — гонку они не убирают и фиксом не считаются.
|
||||
|
||||
## Принятый остаточный риск (решение координатора, 2026-07-12)
|
||||
|
||||
Ревью отметило: `stop_grace_period: 1m` не ограничивает публикацию по
|
||||
времени — при зависании Kafka дольше минуты SIGKILL всё ещё оборвёт batch.
|
||||
Риск принят: штатный тик публикуется за секунды (минута — многократный
|
||||
запас), а ограничивать публикацию таймером значило бы рвать batch уже по
|
||||
построению. Ключевое отличие от исходного флаки: такой обрыв больше не
|
||||
маскируется под «смену фактуры» — precheck непарных строк назовёт его
|
||||
явно, гейт упадёт громко и честно.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] Причина расхождения 8/19 найдена и названа (код, не догадка) —
|
||||
см. «Диагноз» выше.
|
||||
- [ ] Генератор корректно завершается по SIGTERM: текущий batch дописывается
|
||||
- [x] Генератор корректно завершается по SIGTERM: текущий batch дописывается
|
||||
во все четыре топика целиком (flush + запись history), потом процесс
|
||||
выходит; runtime-check дожидается фактической остановки контейнера
|
||||
(направление фикса, пункт 1).
|
||||
- [ ] Seam-check различает «непарные live-строки» и «смена фактуры»:
|
||||
(направление фикса, пункт 1). Плюс `stop_grace_period: 1m` в compose.
|
||||
- [x] Seam-check различает «непарные live-строки» и «смена фактуры»:
|
||||
precheck называет реальную причину (пункт 2).
|
||||
- [ ] Красный сценарий по-прежнему ловится: настоящая смена per-event
|
||||
фактуры внутри `click_id` (инъекция в тесте или контролируемое искажение
|
||||
данных) валит гейт с прежним сообщением — precheck и фикс не сделали
|
||||
проверку мягче.
|
||||
- [ ] Стабильность обоснована структурно (гонка снята по построению:
|
||||
завершение только на границе batch), а не статистикой прогонов;
|
||||
`make generated-history-runtime-check` — N подряд зелёных (N >= 3)
|
||||
как дымовая проверка поверх этого довода, зафиксировано в задаче.
|
||||
- [x] Красный сценарий по-прежнему ловится: контролируемое искажение
|
||||
`referer_url` у события пересекающего визита в `dds.event` уронило гейт
|
||||
с прежним сообщением «per-event фактура меняется на стыке: 18/19» при
|
||||
нулевых счётчиках непарных строк (стендовая приёмка 2026-07-12).
|
||||
- [x] Стабильность обоснована структурно (SIGTERM ставит флаг, тик
|
||||
дописывает все четыре топика + flush + history и выходит на границе
|
||||
batch — тест `test_sigterm_during_publish_finishes_current_batch`);
|
||||
дымовая проверка поверх довода: 3 подряд зелёных
|
||||
`make generated-history-runtime-check` (2026-07-12, прогоны 19:25,
|
||||
19:28, 19:30).
|
||||
|
||||
## Находки стендовой приёмки (2026-07-12, исправлены в этой же задаче)
|
||||
|
||||
Ревью по чтению кода их поймать не могло — вскрылись только прогонами:
|
||||
|
||||
1. **Гейт жил на побочном эффекте бага.** Пересекающие визиты для проверки
|
||||
стыка появлялись только потому, что генератор игнорировал SIGTERM и
|
||||
дописывал ~10 секунд данных до SIGKILL. После фикса live-хвост стал
|
||||
коротким и пересекающих визитов могло не быть вовсе. Фикс: шаг 6
|
||||
runtime-check ждёт не «любую новую STG-строку», а появления
|
||||
пересекающего визита в STG (детерминированное предусловие проверки,
|
||||
то же окно, что у seam-SQL).
|
||||
2. **Часовой пояс в STG-запросах.** Сырые `event_timestamp` наивные и
|
||||
означают UTC, сервер ClickHouse — Europe/Moscow: сравнение с границей,
|
||||
заданной с `+00:00`, уезжало на 3 часа, precheck был зелёным вакуумно
|
||||
(не видел ни одной live-строки). Фикс: явный `'UTC'` в
|
||||
`parseDateTime64BestEffort*` с обеих сторон сравнения (4 места),
|
||||
закреплено контрактными тестами.
|
||||
|
||||
## Blocked by
|
||||
|
||||
|
||||
Reference in New Issue
Block a user