Какие технические события происходят после создания агрегатора событий?

Ответ

После создания и инициализации агрегатора событий (например, экземпляра EventDispatcher в Symfony) система готова к работе по следующему принципу:

  1. Регистрация слушателей (Listeners/Subscribers): Код приложения связывает обработчики с конкретными событиями, используя методы агрегатора, такие как addListener() или addSubscriber(). Эти обработчики помещаются в внутреннюю структуру данных (обычно массив или словарь), сгруппированную по имени события.
  2. Диспетчеризация события: Когда в коде вызывается метод dispatch($event), агрегатор выполняет:
    • Создание объекта события: Если передан строковый идентификатор, агрегатор может инстанцировать соответствующий класс события.
    • Поиск слушателей: Агрегатор находит всех зарегистрированных слушателей для данного события, учитывая их приоритет.
    • Синхронный вызов: Каждый слушатель вызывается последовательно, и ему передается объект события для обработки.
  3. Обработка в слушателях: Внутри слушателя можно:
    • Выполнить бизнес-логику, связанную с событием (отправка email, запись лога, инвалидация кеша).
    • Модифицировать данные внутри объекта события.
    • Остановить дальнейшую передачу события другим слушателям с помощью метода stopPropagation().

Пример на Symfony EventDispatcher:

use SymfonyComponentEventDispatcherEventDispatcher;

// 1. Создание агрегатора
$dispatcher = new EventDispatcher();

// 2. Регистрация слушателя на событие 'user.created'
$dispatcher->addListener('user.created', function (UserCreatedEvent $event) {
    // Логика обработки, например, отправка приветственного письма
    $this->mailer->sendWelcomeEmail($event->getUser());
});

// 3. Где-то в сервисе создания пользователя — диспетчеризация события
$userCreatedEvent = new UserCreatedEvent($newUser);
$dispatcher->dispatch($userCreatedEvent, 'user.created');

Ключевые технические аспекты:

  • Обработка по умолчанию происходит синхронно в том же потоке выполнения.
  • Приоритет слушателей позволяет управлять порядком вызова.
  • Propagation (распространение) события можно остановить, что полезно для реализации механизмов типа "первый обработавший".
  • Агрегатор часто реализует шаблон Наблюдатель (Observer), обеспечивая слабую связанность компонентов системы.

Ответ 18+ 🔞

Давай разберем эту механику, как она работает на самом деле, без этих заумных учебников. Представь, что у тебя есть главный крикун на районе — это наш агрегатор, EventDispatcher. Ты его создал, инициализировал, и он теперь сидит, ждёт своего часа, как паук в центре паутины.

Вот как вся эта движуха происходит:

  1. Регистрация стукачей (Слушателей/Подписчиков). Твоё приложение начинает к этому крикуну подходить и нашептывать: «Слушай, чувак, вот если произойдёт событие user.created — ты сразу крикни вот этому парню (обработчику), он письма отправлять умеет». Или: «А на событие order.paid — вот этим двум ребятам, но сначала тому, у кого приоритет выше». Крикун всё это аккуратненько записывает в свою чёрную книжку (ну, в массив или словарь), сгруппировав по именам событий. Подозрение ёбать чувствую — книжка-то у него уже толстая.

  2. Сам момент диспетчеризации, ёпта. Это когда в коде кто-то орет: «dispatch($event)!». И наш крикун оживает:

    • Создание объекта-новости. Если ему крикнули просто название события строкой, он сам из своего загашника достаёт нужный класс и создаёт объект-событие. Если уже принесли готовый объект — вообще красота.
    • Поиск стукачей в книжке. Он листает свою книжку, находит всех, кто подписан на это событие, и выстраивает их по приоритету — кто первый, кто последний.
    • Синхронный вызов, один за другим. И начинает их вызывать по очереди, сувая каждому в руки тот самый объект события: «На, обработай!». И ждёт, пока тот не закончит.
  3. А вот внутри слушателя-то и происходит вся магия. Там можно:

    • Сделать что надо по бизнесу — письмо отправить, лог записать, кеш почистить.
    • Поменять что-то в самом объекте события (данные-то там живые).
    • Или вообще орануть «СТОП!» через stopPropagation(), и тогда крикун дальше никого вызывать не будет. Доверия ёбать ноль остальным слушателям после этого.

Пример, чтобы совсем понятно стало, на Symfony:

use SymfonyComponentEventDispatcherEventDispatcher;

// 1. Рождается наш главный крикун
$dispatcher = new EventDispatcher();

// 2. К нему подбегает слушатель и регистрируется на событие 'user.created'
$dispatcher->addListener('user.created', function (UserCreatedEvent $event) {
    // А вот и логика: пользователь создался — надо письмо приветственное впарить
    $this->mailer->sendWelcomeEmail($event->getUser()); // Отправляем и не парься
});

// 3. А где-то в сервисе, который пользователей создаёт, происходит триггер
$userCreatedEvent = new UserCreatedEvent($newUser); // Слепили новость
$dispatcher->dispatch($userCreatedEvent, 'user.created'); // И крикуну: «Кричи!»

Важные технические фишки, которые надо держать в голове:

  • Работает всё синхронно по умолчанию. То есть пока все слушатели не отработают, дальше код не пойдёт. Это и хорошо, и терпения ноль ёбать, если слушателей овердохуища и они тяжёлые.
  • Приоритет слушателей — это мощный инструмент, чтобы управлять, кто первый схватит событие. Как в очереди за колбасой в девяностые.
  • Propagation (распространение) — эту цепочку можно оборвать, если один слушатель сказал «хватит». Полезная штука, если событие обработано и дальше смысла гонять его нет.
  • В целом, этот крикун — классическая реализация шаблона Наблюдатель (Observer). Суть в том, что источник события (тот, кто его диспетчерит) нихрена не знает о тех, кто его обрабатывает. Слабая связанность, ёбать копать — это когда компоненты системы не держатся друг за друга как пидарасы шерстяные, а общаются через такие вот крики в пространстве. Красота!