Когда магазину нужен поток событий, а не суточная выгрузка
Коротко
- Оставьте суточную выгрузку там, где решение спокойно ждёт следующего дня.
- Для остатков и рекомендаций сначала запишите, сколько может опоздать событие и что делать при повторе, — и только потом выбирайте потоковый движок.
- Ниже мы проходим учебный контракт на вымышленных заказах: это локальное упражнение, не проверка YTsaurus Flow или работающего магазина.
Что подготовить до выбора технологии
В упражнении получим заполненный контракт свежести, журнал обработки и решение, для каких задач оставить выгрузку. Нужны локальный текстовый редактор и архив с файлами. Для автоматического прохода — установленный Python 3.10 или новее, без дополнительных пакетов. Аккаунты, тариф сервиса, платная модель и данные покупателей не нужны. Файлы редакции доступны без отдельной платы; подключение к зарубежным сервисам инструкция не требует. Состав и требования.
Заложите время на чтение правил и сверку строк; длительность ручного прохода мы не измеряли. Локальный запуск Python у редакции занял около 0,061 секунды, без скачивания, распаковки и чтения. Это время одного процесса, не всей инструкции и не работы потока: запись прохода.
Шаг 1. Назовите решение и его срок
Откройте contract.json.
Для учебного остатка мы выбрали предел задержки 60 секунд. Это наше
условие, не норма торговли и не обещание платформы. Задержку считаем от
времени события в источнике до момента, когда новое значение видно
потребителю: visible − occurred.
Запишите отдельно для цены, остатка, рекомендации и отчёта: кто использует результат, сколько он может ждать, кто отвечает за сбой и какое действие допустимо при устаревании. Например, для учебного остатка просрочка означает сигнал о нарушении; разрешать ли продажу при таком сигнале, нужно решать уже в контракте реального магазина. Наш код витриной не управляет.
Результат шага: вместо требования «нужен real-time» есть конкретный срок и действие при его нарушении. Проверьте всю цепочку до витрины или рекомендательного блока, а не только скорость чтения очереди. Если метки времени берутся с разных машин, заранее согласуйте часы и способ обработки расхождений — иначе вы будете сравнивать разные шкалы.
Шаг 2. Договоритесь, что означает остаток
В наших правилах
stock — физическое наличие одного учебного товара до
резервов. Доступное количество считаем как физический остаток минус
активные резервы заказов. Если ваша выгрузка уже вычитает резервы, эту
формулу переносить нельзя: вы вычтете их повторно.
Откройте events.json. У события есть идентификатор, тип, ключ заказа или товара, версия, количество и две отметки времени. Порядок строк — порядок доставки; время возникновения записано отдельно. Для заказа и отмены используется общая последовательность версий одного заказа. Отмена оставляет нулевой резерв с новой версией, даже если создание заказа ещё не приехало.
Результат шага: понятны значение каждого поля, ключ повторной обработки и правило опоздавшей отмены. Версия должна приходить из согласованного источника, а не назначаться по порядку получения. В рабочей системе укажите срок хранения ключей повторов и согласованный начальный снимок. Опишите, как сверять остаток с учётной системой и разбирать одинаковую версию с разным содержимым. В нашем учебном коде конфликт содержимого не выявляется — такой вход нельзя принимать как безопасный дубль.
Шаг 3. Разберите повторы до запуска
Сначала откройте expected.json: ожидания записаны до исполнения. Затем сопоставьте их с событиями. В начале есть десять единиц; заказ резервирует две, поэтому доступно восемь. Повтор того же события не должен снова уменьшить количество. Повтор с новым идентификатором, но прежней версией заказа, тоже не меняет состояние. Входы и ожидания.
Проверьте неудобный порядок: отмена заказа ORDER-B версии 2 приходит раньше его создания версии 1. В нашей модели позднее создание отклоняется как старая версия, и отменённый резерв не появляется снова. Новый снимок физического остатка устанавливает восемь единиц; старый снимок с десятью не должен его затереть. Ожидаемые решения по строкам.
Результат шага: вы заранее знаете, что должен дать каждый вход. Если ваш источник не даёт сравнимых версий или отмена не однозначна, остановитесь на этом месте и договоритесь о правилах. Название движка не заполнит недостающие поля за вас.
Шаг 4. Запустите и проверьте не только итог
Распакуйте архив, откройте терминал в этой папке и выполните
python3 run.py. Откройте созданные файлы
actual.csv и summary.json. Код сравнивает
каждую строку с ожиданием, затем повторяет весь набор на том же
состоянии и проверяет, что оно не изменилось. При расхождении выполнение
завершится ошибкой. Код
упражнения.
У редакции совпали все десять ожидаемых строк; итог — семь доступных единиц, повторный проход не изменил состояние. У двух доставок задержка превысила учебный предел: у уже устаревшего снимка — 110 секунд, у последнего заказа — 70 секунд. Это задержки из вымышленных меток, не замер сети. Отклонённый снимок не изменил остаток, но остался виден в журнале задержек. Журнал, итог.
Результат шага: совпали строки, итог и повторный проход; отдельно видны нарушения срока. При ошибке не подгоняйте ожидания под выход: проверьте значение остатка, версию заказа и порядок доставки. Наш повтор выполняется в памяти одного процесса: он не проверяет восстановление после падения, сохранность журнала или атомарность внешней записи. Границы упражнения.
Шаг 5. Выберите гарантию и способ обновления
Разработчики YTsaurus Flow описывают три режима обработки. Ниже — смысл гарантий в их описании, а не результаты нашего теста движка.
| Режим | Что допускается | Что проверить магазину |
|---|---|---|
| Exactly-once | По описанию Flow, нет потерь и повторного учёта сообщений при обработке | Где заканчивается транзакция и начинается внешняя запись |
| At-least-once | Повторная обработка допустима | Не повторится ли бизнес-действие |
| At-most-once | Потеря сообщения допустима | Можно ли потерять именно это событие |
Источник всех определений в таблице: техническая статья разработчиков Flow, проверена в дату страницы.
В статье разработчики связывают exactly-once с атомарным изменением состояния и метаданных, включая позиции чтения очередей, в общей транзакции YTsaurus. Описание механизма. В документации Flow отдельно сказано: произвольные внешние эффекты не покрываются exactly-once. Повторный заказ из источника с другим идентификатором тоже требует бизнес-правила, как в нашем упражнении. В нашем упражнении повтор заказа отсеивает проверка версии; внешние записи не выполняются. Для них отдельно проверяйте идемпотентный ключ, подтверждение приёма и поведение при обрыве ответа.
Для итогового отчёта за вчера можно оставить суточную выгрузку, если решение принимают после неё, опоздавшие события попадают в пересчёт, а итог сверяют с учётной системой. Для остатка, который влияет на разрешение продажи сейчас, суточная выгрузка не удовлетворяет нашему учебному пределу в минуту. Это выбор по заданным условиям, не универсальный запрет на пакетную обработку.
Между сутками и непрерывным потоком есть промежуточный вариант: короткие регулярные выгрузки. Сравните их с вашим сроком, прежде чем добавлять потоковую инфраструктуру. Не выбирайте весь магазин целиком: отчёт может остаться суточным, а обновление доступности товара — получить отдельный путь.
Результат шага: для каждой задачи указан способ обновления и причина. Если нет владельца данных, восстановимой истории, правил повторов или действий при просрочке, сначала закройте этот пробел. Более частая доставка сама по себе не доказывает точность остатка или качество рекомендаций.
Как посчитать цену сложности
Посчитайте разницу месячных затрат между потоком и текущей выгрузкой. Учтите вычисления, хранение, разработку и сопровождение, затем добавьте мониторинг, дежурство, сверку и восстановление. Затем сопоставьте её с измеримыми потерями именно от задержки, не со всей выручкой магазина.
Условный расчёт: дополнительная инфраструктура — 12 000 ₽ в месяц,
сопровождение — 8 часов по 2 000 ₽. Итого
12 000 + 8 × 2 000 = 28 000 ₽ дополнительных расходов в
месяц. Все входы придуманы редакцией для формулы; это не тариф Flow и не
рыночная оценка. Если подтверждённых потерь от задержки нет, окупаемость
по этому примеру неизвестна. Открытый код не оплачивает серверы и время
вашей команды.
Как мы проверяли
Редакция Кометы составила правила, вымышленные события и ожидания, затем выполнила локальное упражнение версии 1.0 на Python 3.14.4. Запись учебного контракта 1.0 содержит команду, дату, время процесса и результат. Код, входы, ожидания и выходы доступны в архиве; происхождение файлов и ограничения названы в README. Никаких реальных заказов, клиентских данных, кабинетов или отправок нет.
Гарантии Flow сверены с первоисточником разработчиков; анонс открытия кода — исторический повод, не новость дня этого гайда. Инструкция заканчивается контрактом и его локальной проверкой, не установкой платформы. Смежная задача — поиск по каталогу на YDB: она не заменяет проверку свежести данных.
Источники
- Техническая статья команды YTsaurus Flow — гарантии обработки и транзакции; получена 17.10.2026.
- Документация Flow о гарантиях — границы транзакций и внешние эффекты; получена 17.10.2026.
- Анонс Яндекса об открытии кода — анонс 6 октября 2026; получен 17.10.2026.
- Учебный пакет редакции — контракт, входы, ожидания, код, журнал и запись прохода; 17.10.2026.