Перейти к содержанию

EventRouter

Роутер событий — аналог Slim\App. Создаётся через EventRouterFactory.

Маршруты описываются в отдельном файле, так же как HTTP-маршруты в Slim:

return static function (EventRouter $events): void {
    $events->setPrefix('shop');

    $events->group('order', static function (RouteGroup $group): void {
        $group->listen('created', ReserveStock::class);
        $group->listen('created', SendConfirmationEmail::class);
        $group->listen('{order_id}.paid', MarkOrderPaid::class);
    })
        ->add(EventLogger::class);
};

Рассылка:

$events = EventRouterFactory::create($container);
$events->loadRoutes(require __DIR__ . '/events.php');

$report = $events->dispatch(new Event('shop.order.42.paid', ['amount' => 1500]));

Сам роутер ничего не создаёт: объявления маршрутов хранит корневая группа, таблицу строит RouteTableBuilder, рассылает Dispatcher.


Methods

loadRoutes

Подключить маршруты — обычно файл маршрутов: $events->loadRoutes(require __DIR__ . '/events.php').

public loadRoutes(callable $routes): self

Без кэша просто вызывает $routes($this). С кэшем (route_cache_file в EventRouterFactory::create()):

  • файла кэша нет — вызывает $routes, собирает таблицу и записывает её в файл;
  • файл есть — берёт таблицу и middleware роутера из него, а $routes не вызывает вовсе: не выполняется файл маршрутов и не загружаются классы слушателей.

С кэшем маршруты объявляются только внутри $routes, а loadRoutes() вызывается один раз. Кэш не обновляется сам: после изменения маршрутов файл кэша нужно удалить.

Parameters:

Parameter Type Description
$routes callable

Throws:

если с кэшем loadRoutes() вызван второй раз или middleware добавлен объектом - InvalidRoute


setPrefix

Общий префикс всех топиков — аналог setBasePath() в Slim.

public setPrefix(string $prefix): self

Можно вызвать в любой момент: таблица маршрутов пересобирается сразу, и при ошибке роутер остаётся с прежним префиксом. Пустая строка убирает префикс.

Parameters:

Parameter Type Description
$prefix string

Throws:

если с новым префиксом какой-то шаблон станет некорректным - InvalidTopicPattern


listen

Повесить одного слушателя на шаблон топика.

public listen(string $pattern, string $listener): \Selyusize\EventsRouter\Routing\Route

Несколько слушателей на одно событие — несколько вызовов listen(). Вызываются они строго в порядке объявления, приоритетов нет.

Если шаблон вместе с префиксами групп записан с ошибкой — InvalidTopicPattern. Если класс слушателя не найден или не реализует ListenerInterface — InvalidRoute.

Parameters:

Parameter Type Description
$pattern string шаблон относительно префикса группы; в группе может быть пустым
$listener string

group

Группа маршрутов с общим префиксом и общими middleware.

public group(string $prefix, callable $routes): \Selyusize\EventsRouter\Routing\RouteGroup

Пустой префикс — группа только ради общих middleware.

Parameters:

Parameter Type Description
$prefix string
$routes callable

add

Middleware уровня роутера — аналог $app->add() в Slim.

public add(class-string<\Selyusize\EventsRouter\Contract\Core\MiddlewareInterface>|\Selyusize\EventsRouter\Contract\Core\MiddlewareInterface $middleware): self

Выполняется один раз на событие и оборачивает всех его слушателей, даже если слушателей нет. Подходит для трассировки, общего лога, транзакции. Добавленный последним выполняется первым.

Parameters:

Parameter Type Description
$middleware class-string<\Selyusize\EventsRouter\Contract\Core\MiddlewareInterface>|\Selyusize\EventsRouter\Contract\Core\MiddlewareInterface

setLogger

Лог роутера вместо файлового (FileLogger по пути log_path): например, Monolog проекта.

public setLogger(\Psr\Log\LoggerInterface $logger): self

Сюда пишутся ошибки слушателей, пока не задан свой обработчик через setErrorHandler().

Parameters:

Parameter Type Description
$logger \Psr\Log\LoggerInterface

setErrorHandler

Куда отправлять ошибки слушателей. По умолчанию — в лог роутера (см. setLogger()).

public setErrorHandler(\Selyusize\EventsRouter\Contract\Error\ErrorHandlerInterface $handler): self

Parameters:

Parameter Type Description
$handler \Selyusize\EventsRouter\Contract\Error\ErrorHandlerInterface

setErrorStrategy

Что делать после ошибки слушателя. По умолчанию — ErrorStrategyEnum::Continue.

public setErrorStrategy(\Selyusize\EventsRouter\Dispatch\ErrorStrategyEnum $strategy): self

Parameters:

Parameter Type Description
$strategy \Selyusize\EventsRouter\Dispatch\ErrorStrategyEnum

match

Какие маршруты получат событие с таким топиком.

public match(string $topic): list<\Selyusize\EventsRouter\Routing\RouteMatch>

Возвращает все подходящие маршруты строго в порядке объявления, у каждого — свои параметры из шаблона.

foreach ($events->match('shop.order.42.paid') as $match) {
    $match->getRoute()->getListener();   // MarkOrderPaid::class
    $match->getParameters();             // ['order_id' => '42']
}

Parameters:

Parameter Type Description
$topic string

getRoutes

Все маршруты в порядке объявления, с полными шаблонами и middleware.

public getRoutes(): list<\Selyusize\EventsRouter\Routing\CompiledRoute>

dispatch

Разослать событие всем подходящим слушателям.

public dispatch(\Selyusize\EventsRouter\Contract\Core\EventInterface $event): \Selyusize\EventsRouter\Dispatch\DispatchReport

Слушатели вызываются по очереди в порядке объявления маршрутов. Каждый получает копию события с параметрами своего маршрута в атрибутах и проходит через свои middleware. Исключение в слушателе или его middleware попадает в отчёт и в обработчик ошибок, а дальше всё решает стратегия (setErrorStrategy()): по умолчанию остальные слушатели продолжают работу.

Parameters:

Parameter Type Description
$event \Selyusize\EventsRouter\Contract\Core\EventInterface

run

Воркер: забирать события из источника и рассылать их по одному — аналог $app->run() в Slim.

public run(\Selyusize\EventsRouter\Contract\Source\EventSourceInterface $source, callable|null $afterDispatch = null): int

Возвращает, сколько событий обработано, когда источник закончился. После каждой рассылки вызывает $afterDispatch с отчётом — например, чтобы залогировать ошибки. Исключение из dispatch() (middleware роутера, обработчик ошибок, стратегия Throw) останавливает воркер и выходит наружу: процесс перезапустит менеджер процессов.

$events->run(new AmqpEventSource($channel, queue: 'orders'));

Parameters:

Parameter Type Description
$source \Selyusize\EventsRouter\Contract\Source\EventSourceInterface
$afterDispatch callable|null