Перейти к содержимому

Основы

От событий к результату

Как источник, фильтр, преобразование и приёмник превращают поток разных событий в один результат.

Изучать с ИИ-ассистентом 🤖

Скопируйте промпт и вставьте его в чат с ИИ-ассистентом.

Ты — преподаватель курса «Потоковая обработка».
Тема: «От событий к результату»
О чём: Как источник, фильтр, преобразование и приёмник превращают поток разных событий в один результат.
Текст статьи в Markdown: https://stream-processing-systems.github.io/ru/course/fundamentals/from-events-to-results.md
Опирайся на эту статью. Сначала спроси, как мне удобнее: кратко, пошагово или глубоко с вопросами на понимание. Объясняй на примере из статьи и в её терминах. Если добавляешь сведения, которых в статье нет, явно это отмечай.

В нашем сервисе доставки каждое изменение заказа записывается как событие (event). В магазине сотрудникам стойки выдачи заказов нужно знать, когда заказ упакован, чтобы курьер мог его забрать. Но среди событий заказа есть ещё предложения, ответы и доставки. Если отправлять стойке их все, единственный нужный ей факт потеряется среди остальных. Как превратить поток разных событий в результат, который нужен стойке?

Обработка начинается с источника (source): места, откуда она получает входные записи. Здесь источник передаёт события заказов из системы магазина по мере их поступления. Источник не совпадает с торговым залом, где работает сборщик. Он только поставляет записи о том, что там произошло.

Для заказа ord-1042 источник выдаёт семь событий: от order_placed в 10:00 до order_delivered в 10:25. Для стойки выдачи важно только одно из них.

Первый шаг — фильтр (filter). Он задаёт каждой записи один вопрос: равен ли её event_type значению order_packed? Если да, запись идёт дальше. Если нет, фильтр убирает её с этого пути. Для ord-1042 шесть событий отсеиваются, а одно проходит дальше:

{
"event_id": "evt-005",
"event_type": "order_packed",
"order_id": "ord-1042",
"store_id": "store-418",
"occurred_at": "2026-10-21T10:09:00Z",
"data": {}
}

Отсеять запись здесь не значит удалить её. Другие части системы по-прежнему могут использовать предложение и ваш ответ, просто в ленту стойки выдачи они не попадают.

В событии об упаковке всё ещё больше сведений, чем нужно стойке. Идентификатор и тип события ей не нужны, а data пустое. Ей нужно знать, какой заказ, в каком магазине и когда закончили упаковку.

Второй шаг — преобразование (transformation): правило, которое строит из входной записи новую. Оно копирует order_id и store_id и переименовывает occurred_at в packed_at. Поле occurred_at есть у каждого события, поэтому у него общее название. В выходной записи речь идёт только об упаковке, поэтому packed_at прямо говорит, что означает это время:

{
"order_id": "ord-1042",
"store_id": "store-418",
"packed_at": "2026-10-21T10:09:00Z"
}

Вместе фильтр и преобразование составляют обработчик (processor): компонент, который применяет правила к каждой записи. Его результат попадает в приёмник (sink): место, куда приходят результаты. Здесь приёмник — лента стойки выдачи. В других системах это может быть база данных, файл или вход другого обработчика.

От событий к результату События заказа идут из источника в обработчик: фильтр оставляет события об упаковке, а преобразование строит из них сообщения для приёмника. ОБРАБОТЧИК СОБЫТИЯ ЗАКАЗА ORDER_PACKED СООБЩЕНИЯ ОБ УПАКОВКЕ Источник система магазина Фильтр event_type = "order_packed" Преобразование order_id, store_id, packed_at Приёмник лента стойки выдачи

Источник, обработчик и приёмник — это роли. Небольшая программа может выполнять все три, а большая система может распределить их по многим машинам.

Обработчик разбирает каждое событие об упаковке отдельно: он не смотрит на предыдущие события и ничего не запоминает между ними.

Если одно и то же событие об упаковке придёт к обработчику дважды, в ленту стойки попадут два одинаковых сообщения. Правило никак не может понять, что эту запись оно уже видело.

Лента — это список того, что произошло, а не таблица текущих статусов. Она сообщает, что ord-1042 упакован в 10:09. Из неё не следует, что заказ всё ещё ждёт курьера: на самом деле курьер забрал его в 10:12. Приёмник получает каждое сообщение, но показать его курьеру — отдельная задача.

Некоторым вопросам нужна именно та память, которой у этого правила нет. Магазин ведёт список заказов, которые ждут ответа покупателя. Предложение в 10:04 добавляет ord-1042 в этот список, а ваше согласие в 10:06 убирает его оттуда. Глядя только на согласие, обработчик не может понять, был ли заказ в списке вообще. Что ему нужно хранить между событиями, чтобы это узнать?

  • Источник поставляет входные записи, обработчик применяет к ним правила, а приёмник получает результаты.
  • Фильтр оставляет записи, нужные для результата. Преобразование строит из них результат.
  • Это правило обработки событий об упаковке смотрит на одно событие за раз и ничего не запоминает между событиями.
  • Такое правило не замечает повторное событие и не может ответить на вопрос, который зависит от предыдущих событий.

© 2026 Grig Alex · CC BY-SA 4.0