Место заказов в стартовом мире #74
Notifications
Due Date
No due date set.
Depends on
#70 Приём заказов: нужен ли слепку слой сырья
ddmitry/clickstream-data-platform
#72 Расхождения A–D и опоздания: механика, доли и что обещано
ddmitry/clickstream-data-platform
Reference: ddmitry/clickstream-data-platform#74
Reference in new issue
Block a user
Part of #69.
Вопрос
Появляются ли слепки заказов в стартовом мире, который
make upзаливает на пустой стенд, и что это делает с описью?Сегодня стартовый мир — восемь модельных дней событий; опись (
data/world-inventory.json) хранит паспорт мира и хеши дней,world-initзаливает их при подъёме, аmake check-clickhouseсверяет счёт по дням с описью (#42).Решить: входят ли заказы в тот же артефакт, как выглядит их хеш при окне изменяемости K (слепок дня D меняется ещё K дней), и что тогда сторожит проверка на стенде.
Вход из #72 — находка холодного ревью, которую там закрыть нечем.
При сдвиге отправки на день (#71) прогон дня D отправляет слепок дня D−1, поэтому
слепок последнего сыгранного дня не отправляется вовсе. На стартовом мире это день
7, и у 18 из 73 пар поздний назначенный заказ падает как раз на него (замерено
на каноническом зерне:
plan.counters(seed, 8).pairs= 73, из них 18 имеютmax(pair_order_days) == 7).Следствие: карта соответствий
dds.identity_mapстроится из моста «событиеpurchase↔ заказ», а этих заказов в хранилище не будет — четверть пар стартовогомира в карту не попадёт. Счётчик пар при этом их считает: он смотрит только на
горизонт (
plan.py,np.all(pair_order_days < days)) и про слепки не знаетничего. Опись покраснеет не от ошибки, а по построению.
Две двери, и обе здесь:
и число в §6 резолюции #72 (
N − 7) поедет;а «доехали ли эти заказы в отправленном слепке».
Со стороны #72 подпёрто тем, что назначенные планом заказы не опаздывают и их
события не теряются, — но заказ, у которого слепка нет вовсе, этим не спасти.
Резолюция
Рамка. Стартовый мир — не полный мир, а мир, остановленный на границе суток
7|8. Генератор играет два источника с разными темпами: поток Метрики и ночную
выгрузку бэкенда магазина. Разные темпы и дают всё остальное.
1. Слепков семь — дни 0…6
world-initиграет восемь дней одним прогономbatch --day 0 --days 8. Сосдвигом (#71) прогон дня D отправляет слепок дня D−1, поэтому уезжают слепки
дней 0…6. Слепок дня 7 снят на границе суток и уедет первым же ходом мира.
Особого режима у стартового мира не заводится: команда остаётся прежней, правило
отправки живёт в одном месте — в проигрывателе. Генератору тикет не стоит ничего.
Окно изменяемости хеш слепка не трогает. Вопрос тикета снят ещё #71: слепок
дня D — чистая функция (зерно, D), окно живёт внутри него. Дышат заказы, а не
байты слепка, поэтому строка-слепок получает обычный хеш, как день.
2. Что из этого видно снаружи
У последнего прожитого дня клики есть, а заказов нет. Глубже: заказ дышит
статусами ещё K дней, а последний приехавший слепок — день 6. Поэтому день 0
виден дожившим до конца окна, день 1 — прожившим шесть дней, …, день 6 — только
что родившимся. График выручки заваливается к правому краю и дозаполняется,
пока мир едет.
Это не издержка стенда, а главный наблюдаемый эффект второго источника: ночная
выгрузка отстаёт, витрина дозаполняется задним числом, свежие дни предварительны.
«Почему у нас последние дни на дашборде проседают» — обычный вопрос на
собеседовании, и уверенно на него отвечает тот, кто это видел.
3. Что кладётся в опись
За правилом стоит разведение двух вещей, которые выглядят одинаково:
сдвиг не пройдёт молча. Читателя ему не нужно — его читает
git diff. Правкагенератора обходится ему в «пересобрал опись, принял diff».
за него каждая правка генератора: число надо пересчитать и убедиться, что оно
означает то же самое.
Отсюда: хеш кладём всегда, счётчик — только когда назван его читатель.
Читателей у счётчиков описи ровно два. Живой сегодня один:
make check-clickhouseчитает события по дням — всё ли доехало вods.event. Второйпридёт этапом 4: проверка сверки читает счётчики классов расхождений — правильно
ли расклассифицировано. Если к тому времени читателя у них так и не окажется, та
же бритва режет и их.
У числа склеенных пар и uniq известных пользователей читателя нет вовсе:
генератор они не сторожат (сторожит хеш), транспорт не сторожат (сторожит счёт
событий), а как опора лабы протухают со второго дня жизни стенда.
4. Что сторожит проверка на стенде
Опись описывает мир, а не доставку. Хеш слепка сторожит генератор — те ли
байты он выдал. Доехали ли они до
ods.order_snapshot— вопрос стенда, иотвечают на него его проверки и даги качества. Граница там же, где кончается
работа генератора: положить в Kafka.
Поэтому счёта строк у слепка в описи нет. У событий такое число есть, и
make check-clickhouseсверяет по нему приход вods.event, — но у слепков читателясегодня назвать нечем, а счётчик впрок правило выше и запрещает. Понадобится
проверка приёма заказов — число заведётся тогда же, вместе с ней.
Счётчики сторожат только дни с закрытым окном — на стартовом мире один, на
эталонном семь (
N − 7, из #72). Это сходится с основанием, по которому размерымиров и выбирались:
inventory.pyназывает восемь дней «первым замкнутым цикломокна K = 7», четырнадцать дней эталонного дают неделю таких.
Расхождения с принятым
Вносятся тем же коммитом, что и спека второго источника.
Мастер-спека:
мир едет. Лаба склейки не страдает: её ядро — неравенство
uniq(посетителей) > uniq(людей), а оно верно в любой день.пользователей» и «число двухкуковых покупателей» растут, пока мир едет. «Uniq
кук» стабилен, но читателя у него тоже нет — а правило одно на обе стороны, и
счётчик без читателя не кладётся. Назовётся читатель — вернётся вместе с ним.
закрытым окном». У открытых дней эти числа верны до первого хода мира.
Спека генератора получила рамку владельца отдельным разделом «Чем меряется
генератор» (коммит
34267e8): генератор меряется выходом, повторимы эффекты, ане числа, хеши обещают видимость сдвига. Правило описи выше — прямое следствие.
Отклонено
свежем стенде исчезает класс
awaiting_order— сюжет «вчера не сходилось,сегодня сошлось», ради которого #71 сдвиг и делал. Заводит в CLI рычаг «дошли
последний слепок», который дальше тащит каждое изменение, и делает стартовый
мир особым случаем ровно там, где #71 его убирал. И изображает магазин с
мгновенной выгрузкой, каких не бывает.
бы верным ровно до первого хода мира, а мир заведён, чтобы ехать: рядом стоит
пульт с выключателем.
разницу дешевле объяснить словами в спеке, чем сторожить числом.
awaiting_orderпропал бынавсегда, а не только на свежем стенде.
Мир перестал бы быть чистой функцией зерна и начал зависеть от того, где мы
остановились.
Замеры
Каноническое зерно, снято здесь, а не перенесено:
Доехавшие считаются как
plan.counters(seed, N−1).pairs— тот же счётчик нагоризонте на день короче;
край горизонта, а не свойство дня.
Швы соседям
не опаздывают — сохраняет обе стороны моста до появления в
dds.identity_map»сильнее, чем верно: заказ может отсутствовать не из-за потери или опоздания, а
потому что его слепок ещё не выгружен. Механики #73 это не задевает. Там же
четвёртое наблюдаемое свойство опирается на числа посетителей, известных
пользователей и пар — свойство мира остаётся, но числом в описи не
записывается.
как решена форма записи на проводе и канонический порядок строк. Туда же
вопрос: шлёт ли прогон дня 0 пустой слепок дня −1 или не шлёт ничего.
awaiting_orderи недозаполненный правый край выручки. Это норма, а неполомка; как это назвать менти — за витринами.
семь дней с закрытым окном. Правки потребуют только числа.