fix(stand): находки ревью — диагноз не утверждает причину, комментарии не врут
Зачем Холодное ревью нашло три места, где написанное сильнее сделанного. Что - Непустая таблица брака больше не выдаётся за доказательство сломанного разбора. Модельного дня у брака нет, обрамить его нечем, и строки прежних уроков лежат в нём месяц: после первого же урока с мусором проверка давала бы неверный диагноз навсегда. Теперь она даёт признак, по которому причину отличают, — сошлась недостача с числом брака или нет. - Комментарий у world-init обещал, что расхождение числа дней с STARTING_DAYS поймают счётчики. Это неправда в одну сторону: лишний день ложится за рамкой дат описи. Обещание убрано, дыра названа. - Довод «даг next_day этапа 5 продолжит ось» опирался на несуществующий этап; заменён настоящей причиной — заливка замыкает цепь разовых служб. - Потолок ожидания 300 с получил обоснование замером с кратностью, а сам скрипт — честную оговорку: его обещание работает на пустом стенде, на живом ждать нечего. - Третья, пропущенная ссылка на снятый порог скорости дня убрана из спеки. - Даты замеров в карте целей разведены: #42 менял три цели, а не шесть. Проверка Обе ветви диагноза сняты заново на живом стенде: без брака — «не доехали», с браком — признак различения. Стенд восстановлен, все 9 проверок зелёные, брака 0. make lint, typecheck, config-test, test (407 тестов) зелёные. Ссылка: #42
This commit is contained in:
+6
-7
@@ -251,8 +251,9 @@ services:
|
||||
# Что это за дни и каким мир обязан выйти — data/world-inventory.json.
|
||||
#
|
||||
# Число дней стоит здесь числом: YAML не читает Python, и одно из двух мест
|
||||
# (второе — `STARTING_DAYS` в inventory.py) лишнее по построению. Разъедутся
|
||||
# они — покраснеют счётчики `make check-clickhouse`.
|
||||
# (второе — `STARTING_DAYS` в inventory.py) лишнее по построению. Правя одно,
|
||||
# правьте второе — на страже тут никто не стоит: залей эта служба лишний
|
||||
# день, он лёг бы за рамкой дат описи и остался бы незамеченным.
|
||||
#
|
||||
# Повторный `make up` заливает мир заново, и это не оплошность: `WatchID` у
|
||||
# событий те же, ReplacingMergeTree схлопнет повтор в ODS. Сырьё в STG при
|
||||
@@ -309,11 +310,9 @@ services:
|
||||
# упавшим для --wait.
|
||||
clickhouse-init:
|
||||
condition: service_completed_successfully
|
||||
# По той же причине — и ещё по одной. Заливка стартового мира идёт
|
||||
# последней в цепи разовых служб, и зависимого ей взять больше негде.
|
||||
# Заодно это правда про порядок: даг `next_day` этапа 5 продолжает ось с
|
||||
# того дня, на котором заливка остановилась, — Airflow приходит в мир,
|
||||
# который уже есть.
|
||||
# По той же причине. Заливка стартового мира идёт последней в цепи
|
||||
# разовых служб, и зависимого ей взять больше негде: долгоживущие службы
|
||||
# данных не ждут, а `airflow-init` эту цепь и так замыкает.
|
||||
world-init:
|
||||
condition: service_completed_successfully
|
||||
entrypoint: ["/bin/bash"]
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
|
||||
## Карта целей
|
||||
|
||||
Стенд нужен трём целям из семи. Цена — замер 7 августа 2026 года, см. «Что
|
||||
проверено».
|
||||
Стенд нужен трём целям из семи. Цена — замер, см. «Что проверено»: `make test`,
|
||||
`make smoke` и `make check-clickhouse` перемерены 7 августа 2026 года, их #42
|
||||
менял; остальные три стоят с замера 6 августа.
|
||||
|
||||
| Цель | Что утверждает | Стенд | Цена |
|
||||
|---|---|---|---|
|
||||
@@ -204,11 +205,13 @@ Kafka → STG → ODS, и живёт он в `make check-clickhouse`.
|
||||
Что новая проверка **умеет краснеть**, снято двумя поломками того же дня, и
|
||||
проверялись обе ветви её диагноза. Снесли партицию `2026-06-03` в
|
||||
`ods.event_rep` — проверка покраснела, показала недостающий день и назвала
|
||||
адрес: «события не доехали до ODS, начните с чтеца топика». Затем положили в
|
||||
сырьё заведомо негодную строку — брак появился, и проверка сменила диагноз на
|
||||
«сломан разбор, начните с `ods.event_errors_dist`». Строки опыта убраны, день
|
||||
переигран `make generate-batch GENERATOR_DAY=2`; счёт вернулся к 401 185, и
|
||||
это заодно показало дедупликацию: повтор дня не удвоил счёт под `FINAL`.
|
||||
адрес: «таблица брака пуста, события не доехали до ODS, начните с чтеца
|
||||
топика». Затем положили в сырьё заведомо негодную строку — брак появился, и
|
||||
диагноз сменился на второй, с признаком для различения: «сойдётся недостача с
|
||||
числом брака — сломан разбор, не сойдётся — брак от прежних опытов». Строки
|
||||
опыта убраны, день переигран `make generate-batch GENERATOR_DAY=2`; счёт
|
||||
вернулся к 401 185, и это заодно показало дедупликацию: повтор дня не удвоил
|
||||
счёт под `FINAL`.
|
||||
|
||||
Замеры 6 августа 2026 года, стенд поднят заранее. Время взято по `time` и
|
||||
совпадает с тем, что цель печатает сама. Оно плавает от прогона к прогону:
|
||||
|
||||
@@ -888,9 +888,8 @@
|
||||
пока число правдоподобно, само по себе оно ничего не сторожит, и
|
||||
подгонять поведение под его край не надо. Настоящий предел здесь другой и
|
||||
считается в другой валюте — дневной бюджет событий: события корзины
|
||||
входят в те самые «около 50 тыс.», на которых стоят опись (#42) и
|
||||
порог скорости дня. Упрётся будущая правка — двигать надо бюджет и его
|
||||
причины, а не долю.
|
||||
входят в те самые «около 50 тыс.», на которых стоит опись (#42). Упрётся
|
||||
будущая правка — двигать надо бюджет и его причины, а не долю.
|
||||
|
||||
Решено при исполнении #41 (2026-08-07). Первые два пункта — решения владельца
|
||||
грилингом 7 августа 2026 года, внесённые как есть; остальные приняты при
|
||||
|
||||
@@ -94,6 +94,11 @@ on_signal() {
|
||||
# Таблица брака здесь не второе утверждение, а объяснение первого. Утверждай мы
|
||||
# «брака нет», проверка краснела бы навсегда после первого же урока, где менти
|
||||
# нарочно отправил в топик мусор, — и краснела бы не о том.
|
||||
#
|
||||
# По той же причине непустой брак сам по себе ничего не доказывает: модельного
|
||||
# дня у брака нет, обрамить его нечем, и строки прежних уроков лежат в нём
|
||||
# месяц. Поэтому объяснение не утверждает причину, а даёт признак, по которому
|
||||
# её отличают: сошлась недостача с числом брака — разбор, не сошлась — доставка.
|
||||
check_starting_world() {
|
||||
local expected actual broken first_date last_date
|
||||
|
||||
@@ -122,11 +127,11 @@ check_starting_world() {
|
||||
FORMAT TSV")"
|
||||
printf 'Опись мира ожидает (дата, событий):\n%s\n' "$expected" >&2
|
||||
printf 'В ods.event лежит:\n%s\n' "${actual:-— ничего —}" >&2
|
||||
if [[ -n "$broken" ]]; then
|
||||
printf 'В ods.event_errors по классам брака:\n%s\n' "$broken" >&2
|
||||
fail 'счёт разошёлся с описью, и в таблице брака есть строки: сломан разбор — начните с ods.event_errors_dist и матвью ods.event_mv'
|
||||
fi
|
||||
if [[ -z "$broken" ]]; then
|
||||
fail 'счёт разошёлся с описью, а таблица брака пуста: события не доехали до ODS — начните с чтеца топика stg.hits_raw_kafka и матвью приёма stg.hits_raw_mv'
|
||||
fi
|
||||
printf 'В ods.event_errors по классам брака:\n%s\n' "$broken" >&2
|
||||
fail 'счёт разошёлся с описью, и в таблице брака есть строки. Сойдётся недостача с их числом — сломан разбор, смотрите матвью ods.event_mv; не сойдётся — брак остался от прежних опытов, а события не доехали: смотрите чтеца топика stg.hits_raw_kafka'
|
||||
}
|
||||
|
||||
assert_ddl_queue_completed() {
|
||||
|
||||
@@ -15,10 +15,19 @@
|
||||
# брака. Сломайся разбор — события уедут в `*_errors`, сумма сойдётся, ожидание
|
||||
# кончится, и поломку назовёт `make check-clickhouse`. Ждать здесь одних годных
|
||||
# событий значило бы висеть пять минут вместо внятного ответа.
|
||||
#
|
||||
# Обещание у скрипта ровно одно и только на пустом стенде: «мир доехал». На
|
||||
# живом стенде мир уже лежит в ODS, условие истинно на первой же попытке, и
|
||||
# ждать тут нечего — повторная заливка ничего не добавляет, её схлопнет
|
||||
# дедупликация. Утверждать после неё «доехала именно эта заливка» скрипт не
|
||||
# может и не пытается: у события нет отметки, которым прогоном оно приехало.
|
||||
set -Eeuo pipefail
|
||||
|
||||
readonly ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
readonly INVENTORY="${ROOT_DIR}/data/world-inventory.json"
|
||||
# Потолок ожидания — 300 с: больше чем вдесятеро от замеренных 22,5 с, за
|
||||
# которые заливка отдаёт восемь дней в Kafka (карта проверок, «Что проверено»).
|
||||
# Это не бюджет, а предел, за которым ждать бессмысленно и надо читать журнал.
|
||||
readonly ATTEMPTS=100
|
||||
readonly PAUSE_SECONDS=3
|
||||
# Как часто отчитываться о ходе: молчащая минуту команда выглядит зависшей.
|
||||
|
||||
Reference in New Issue
Block a user