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

Основы

Что сообщает событие?

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

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

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

Ты — преподаватель курса «Потоковая обработка».
Тема: «Что сообщает событие?»
О чём: Что содержит полезная запись о событии и чем событие отличается от команды и текущего состояния.
Текст статьи в Markdown: https://stream-processing-systems.github.io/ru/course/fundamentals/what-an-event-tells-us.md
Опирайся на эту статью. Сначала спроси, как мне удобнее: кратко, пошагово или глубоко с вопросами на понимание. Объясняй на примере из статьи и в её терминах. Если добавляешь сведения, которых в статье нет, явно это отмечай.

В нашем сервисе доставки продуктов система реагирует на каждое изменение заказа, когда оно поступает. Сборщик, сотрудник магазина, который собирает ваш заказ, не нашёл красные яблоки и предложил вместо них зелёные яблоки. Вы только что согласились. Если система получит только «заказ обновлён», она не поймёт, показать ли новое предложение или подтвердить то, которое вы приняли. Что должна содержать запись об этом изменении, чтобы система могла по ней действовать?

В 10:06 вы нажимаете «Принять». Это действие происходит один раз, в приложении. Затем система создаёт запись, которая его описывает. Эта запись и есть событие (event): данные о том, что произошло, вместе с контекстом, который нужен, чтобы это понять1.

В отличие от действия, запись можно сохранить, скопировать и передать другим программам. Чтение записи не повторяет действие: запись о том, что заказ упакован, ничего не упаковывает. Кроме того, запись может дойти до программы через какое-то время после самого действия.

Чтобы обработать ваш ответ, магазину нужны ответы на несколько вопросов. Наш сервис записывает каждый ответ в отдельное поле:

ВопросПолеВ вашем ответе
Что произошло?event_typereplacement_accepted
Какой заказ?order_idord-1042
Какой магазин?store_idstore-418
Какие подробности?dataЗамена, на которую вы согласились: green apples 1kg
Когда это произошло?occurred_at21 октября 2026 года, 10:06 UTC
Какая это запись?event_idevt-004

Целиком событие выглядит так:

{
"event_id": "evt-004",
"event_type": "replacement_accepted",
"order_id": "ord-1042",
"store_id": "store-418",
"occurred_at": "2026-10-21T10:06:00Z",
"data": {
"replacement_item": "green apples 1kg"
}
}

Z в конце времени означает UTC, общую шкалу времени, которая не зависит от часового пояса магазина.

У всех событий нашего сервиса одинаковые поля. Различаются их значения, а содержимое data зависит от того, что произошло. Предложению нужны и исходный товар, и замена. Событию об упаковке подробности не нужны вовсе: тип, заказ и время уже говорят, какой заказ упакован и когда. В других системах поля называются и располагаются иначе, но отвечают на те же вопросы.

occurred_at говорит, когда вы согласились: в 10:06. Но это поле не говорит, когда программа получила запись. Запись может прийти в 10:06, а может в 10:08, после задержки в сети. Чтобы знать время получения, принимающая программа должна отметить его отдельно.

Записи могут приходить и не в том порядке, в котором происходили описанные действия. Если запись о предложении, сделанном в 10:04, задержится, запись о вашем согласии в 10:06 может прийти раньше. Программа, которая доверяет порядку получения, увидит ответ раньше вопроса.

Время события и время получения Предложение сделано в 10:04, согласие — в 10:06, но запись о предложении задержалась, и согласие пришло первым. ПОРЯДОК ДЕЙСТВИЙ ПОРЯДОК ПОЛУЧЕНИЯ ЗАДЕРЖКА Предложение 10:04 Согласие 10:06 Согласие пришло первым Предложение пришло вторым

Идентификатор события и идентификатор заказа

Заголовок раздела «Идентификатор события и идентификатор заказа»

event_id и order_id похожи, но отвечают на разные вопросы. event_id обозначает одну запись. order_id обозначает заказ, к которому эта запись относится.

У одного заказа много событий. У заказа ord-1042 их семь: от evt-001, когда его оформили, до evt-007, когда его доставили. Если бы система различала записи по идентификатору заказа, у всех семи фактов была бы одна метка, и их нельзя было бы отличить друг от друга. Если бы она группировала записи по идентификатору события, каждая запись осталась бы сама по себе, и история заказа рассыпалась бы.

Одну и ту же замену можно описать тремя способами, и каждый означает своё:

ВидПримерЧто он сообщает
Событиеreplacement_accepted в 10:06Что-то произошло в прошлом.
Команда (command)«Пожалуйста, замените красные яблоки».Просьба к сборщику. Замена, возможно, ещё не произошла.
Текущее состояние (current state)«Упакован»Что с заказом сейчас, как это видит какая-то система в данный момент.

Если их перепутать, ответы будут неверными. Если система примет команду за событие, она может сообщить вам, что зелёные яблоки уже в пакете, хотя сборщик ещё не снял их с полки. Если хранить только последний статус, система будет знать, что заказ «Упакован», но не узнает, когда закончили упаковку и была ли принята замена. Запись о текущем заказе могла бы хранить эти подробности в дополнительных полях. События сохраняют каждое изменение: когда заказ доставят, статус сменится на «Доставлен», а событие об упаковке в 10:09 останется на месте.

Теперь у магазина есть события с понятным смыслом, но ему ещё нужны результаты. Допустим, он хочет ленту, которая сообщает о каждом упакованном заказе. Ваше согласие относится к истории заказа, но об упаковке ничего не говорит. Какие события должны попасть в эту ленту и что должно быть в каждом её сообщении?

  • Событие — это запись о том, что произошло. Полезное событие сообщает, что произошло, с каким заказом, когда и с какими подробностями.
  • occurred_at показывает, когда что-то произошло, но не когда пришла запись. Записи могут приходить не в том порядке, в котором происходили действия.
  • Идентификатор события обозначает одну запись. Идентификатор заказа связывает все записи об одном заказе.
  • Событие сообщает о прошлом, команда просит о действии, а текущее состояние описывает настоящее.
  1. CloudEvents v1.0.2 specification.

© 2026 Grig Alex · CC BY-SA 4.0