handbookНаписать

lessons/003-events-instead-of-calls/step-3/README.md · тема · 4 языка · 15 тестов

Шаг 3: независимые подписчики ​

Диспетчер ловит ошибку каждого слушателя, отдаёт её в отчёт и зовёт следующих: упавшая аналитика больше не мешает письму.

Урок: События вместо прямых вызовов. Предыдущий шаг: доменное событие и синхронный диспетчер.

Что было ​

Checkout публиковал OrderPlaced, слушатели подписывались сами. Но ошибка любого слушателя прерывала dispatch, долетала до place, и все, кто был подписан после упавшего, не срабатывали.

Что меняем ​

  • EventDispatcher получает в конструкторе report - функцию, которая принимает ошибку. В приложении она пишет в лог и в трекер ошибок.
  • dispatch оборачивает вызов каждого слушателя: ошибка уходит в report, цикл идёт дальше. В Go Dispatch больше не возвращает error, а Place - тем более: оформлению нечего сообщить вызывающему коду о чужих реакциях.
  • Слушатели и касса не меняются.

Здесь меняется поведение, и это единственное намеренное изменение в уроке. Тест с лежащей аналитикой теперь утверждает обратное: place не падает, сборка запрошена, письмо ушло, а в отчёте одна ошибка "analytics is down". Первый тест и тест без подписчиков остались прежними.

Как это собирается ​

Место сборки создаёт report вместе с диспетчером: здесь решается, куда уходят сбои реакций. Подписки те же, что на шаге 2. Пример оформляет те же два заказа: оба оформлены, оба письма ушли, а сбой аналитики виден в строке reported.

Сценарий целиком с выводом: пример на PHP, он же на Go, Python и TypeScript в панели кода.

Что стало лучше ​

  • Реакции действительно независимы: сбой одной не трогает другие, порядок подписки больше не влияет на результат.
  • place сообщает только о своём: заказ сохранён. Вызывающему коду не нужно разбираться с ошибками почты или аналитики.
  • Сбои не теряются молча: каждый проходит через report и попадает туда, где их увидят.

Итог ​

За три шага касса прошла путь от "знаю всех и зову сама" до "сохранила заказ и сообщила". Реакции подписываются при сборке приложения, добавляются без правки кассы и падают в одиночку.

Чего этот шаг не решает:

  • Повтора нет: упавшая реакция просто записана в отчёт. Для аналитики это нормально, для сборки заказа - нет.
  • Диспетчер синхронный: письмо отправляется в том же запросе, и медленный сервис тормозит оформление.
  • Если процесс упадёт после сохранения заказа, но до рассылки, событие потеряется. Когда реакция обязана случиться, событие пишут в ту же транзакцию и рассылают отдельно - см. Outbox.

Сам приём разобран в темах Доменное событие и Наблюдатель.

Запуск: make test T=lessons/003-events-instead-of-calls/step-3

© 2014-2026 Тимур ТурдыевСайт и справочник работают на VPS от AdminVPS