rabbitevents/listener
Composer 安装命令:
composer require rabbitevents/listener
包简介
The Listener component of the RabbitEvents library.
关键字:
README 文档
README
The RabbitEvents Listener component provides an API for handling events published across the application structure. More information is available in the Nuwber's RabbitEvents documentation.
If you only need to handle events, you can use the RabbitEvents Listener separately from the main library.
Table of Contents
- Installation via Composer
- Configuration
- Register a Listener
- Defining Listeners
- Middleware
- Stopping The Propagation Of An Event
- Console Commands
- Supervisor Configuration
- Logging
Installation via Composer
RabbitEvents Listener can be installed via the Composer package manager:
composer require rabbitevents/listener
After installing Listener, you can execute the rabbitevents:install Artisan command, which will install the RabbitEvents configuration file and RabbitEventsServiceProvider into your application:
php artisan rabbitevents:install
Configuration
Details about the configuration are described in the library documentation.
Register a Listener
The listen property of RabbitEventsServiceProvider contains an array of all events (keys) and their listeners (values). You can add as many events to this array as your application requires.
You can even register listeners using the * as a wildcard parameter, allowing you to catch multiple events with the same listener. Wildcard listeners receive the event name as their first argument and the entire event data array as their second argument.
<?php use RabbitEvents\Listener\ListenerServiceProvider; class RabbitEventsServiceProvider extends ListenerServiceProvider { protected $listen = [ 'payment.succeeded' => [ 'App\Listeners\SendNotification', 'App\Listeners\ChangeUserRole@process', function($payload) { Log::info('Payment Succeeded', $payload); }, ['App\Listeners\ChangeUserRole', 'process'] ], 'item.*' => [ AllItemEventsListener::class ] ]; }
Registering Listeners via Attributes
Instead of manually registering listeners in the $listen array, you can use the #[Listener] attribute on your listener class or methods.
Class Listener
use RabbitEvents\Listener\Attributes\Listener; #[Listener(event: 'payment.succeeded')] class SendNotification { public function handle($payload) { // ... } }
Method Listeners
class UserEventSubscriber { #[Listener(event: 'user.created')] public function onUserCreated($payload) {} #[Listener(event: 'user.deleted')] public function onUserDeleted($payload) {} }
To enable auto-discovery, ensure you are using the RabbitEventsServiceProvider.
Listener Discovery
Listener discovery is enabled by default. The service provider will automatically scan your app/Listeners directory for classes with the #[Listener] attribute.
If you wish to disable auto-discovery, you can override the shouldDiscoverEvents method in your RabbitEventsServiceProvider:
/** * Determine if events and listeners should be automatically discovered. */ public function shouldDiscoverEvents(): bool { return false; }
By default, the listenerDirectory is set to app_path('Listeners'). You can override this method if your listeners are located elsewhere.
/** * Get the listener directory path. */ protected function listenerDirectory(): string { return app_path('Bus/Listeners'); }
When discovery is enabled, the service provider will scan the directory for classes with the #[Listener] attribute and register them automatically.
Defining Listeners
Event listeners receive the event data in the method provided in the $listen definition. If no method is provided, the handle method will be called. Within the handle method, you can perform actions necessary to respond to the event:
Example of The Event Listener class
<?php class SendNotification { public function handle($eventPayload) { Mailer::to(Arr::get($eventPayload, 'user.email')) ->subject('Payment Succeeded') ->message('...'); } }
Example of The Wildcard Event Listener class
<?php class AllItemEventsListener { public function handle($event, $payload) { match($event) => [ 'item.created' => ..., 'item.deleted' => ..., 'item.updated' => ..., ]; } }
Handling Protobuf Messages
If you publish a Protobuf message, the Listener will automatically receive the hydrated object instance.
Note: You must install the
rabbitevents/protobufpackage to use this feature.
<?php use App\Messages\AccountCreated; class AccountListener { public function handle(AccountCreated $message) { // $message is an instance of App\Messages\AccountCreated $id = $message->getId(); } }
Middleware
A Listener middleware allows you to wrap custom logic around the execution of a listener, reducing boilerplate in the handlers themselves. For example, you have an event charge.succeeded which can be handled in several APIs but only if this payment is for a specific entity.
Without middleware, you had to check the entity type in a listener's handle method.
<?php /** * Handle payment but only if the type is 'mytype' * * @param array $payload * @return void */ public function handle($payload) { if (\Arr::get($payload, 'entity.type') !== 'mytype') { return; } Entity::find(\Arr::get($payload, 'entity.id'))->activate(); }
It is okay if you have only one listener. What if many listeners must implement the same check at the first line of the handle method? The code will become a bit noisy.
Instead of writing the same check at the start of each listener, you could define listener middleware that handles an entity type.
<?php namespace App\Listeners\RabbitEvents\Middleware; class FilterEntities { /** * @param string $event the event name. Passing only for wildcard events * @param array $payload */ public function handle([$event,] $payload) { return !\Arr::get($payload, 'entity.type') == 'mytype'; } }
In this example, you see that if you need to stop the propagation, just return false.
After creating listener middleware, they can be attached to a listener by returning them from the listener's middleware method or as an array item from the $middleware attribute.
<?php use App\Listeners\RabbitEvents\Middleware\FilterEntities; class PaymentListener { public array $middleware = [ FilterEntities::class, `App\Listeners\RabbitEvents\Middleware\AnotherMiddleware@someAction`, ]; /** * @param string $event the Event Name. Passing only for wildcard events * @param array $payload */ public function middleware([$event, ]$payload) { return !\Arr::get($payload, 'entity.type') == 'mytype'; } }
You can see that you are also able to specify which method of the attached middleware class should be called.
This is just an illustration of how you could pass middleware to the listener. You could choose the way you prefer.
Stopping The Propagation Of An Event
Sometimes, you may wish to stop the propagation of an event to other listeners. You can do so by returning false from your listener's handle method.
Console Commands
Command rabbitevents:listen
There is a command that registers events in RabbitMQ:
php artisan rabbitevents:listen event.name --memory=512 --tries=3 --sleep=5 -v
This command registers a separate queue in RabbitMQ bound to an event. As rabbitevents:listen registers a queue, you should run this command before you start publishing your events. Nothing will happen if you publish an event first, but it will not be handled by a Listener without the first run.
To start listening to all events registered in the application, you can run without any event names:
php artisan rabbitevents:listen
or mention events separated by commas:
php artisan rabbitevents:listen event.one,event.two,event.n
If the list of events is too long, the queue name will be created as an MD5 checksum of the lengthy queue name. This was implemented because the AMQP driver does not accept longer names.
You can start listening to an event only by using the rabbitevents:listen command, so you could use some system such as Supervisor
or pm2 to control your listeners.
If your listener crashes, then managers will rerun your listener, and all messages sent to a queue will be handled in the same order as they were sent. There is a known problem: as queues are separated and you have messages that affect the same entity, there's no guarantee that all actions will be done in an expected order. To avoid such problems, you can send message time as a part of the payload and handle it internally in your listeners.
Options
--service= - By default, it's config('app.name'). When a queue starts, the name of the service becomes a part of a queue name: service:event.name. You could override the first part of a queue name by this option.
--memory=128 - The memory limit in megabytes. The RabbitEvents have restarting a worker if the limit is exceeded.
--timeout=60 - The length of time (in seconds) each Message should be allowed to be handled.
--tries=1 - The Number of times to attempt to handle a Message before logging it failed.
--sleep=5 - How long in seconds a worker would wait before the next try to handle a failed message.
--quiet - Hide console output.
-v - Verbosity. Enables a stack trace for Exceptions.
Command rabbitevents:list
To get the list of all registered events, please use the command rabbitevents:list.
php artisan rabbitevents:list
Event Discovery Caching
If you are using event discovery, scanning the listener directory on every request (or worker boot) can be slow in large applications. You can cache the discovered events using the rabbitevents:cache command:
php artisan rabbitevents:cache
This command will generate a bootstrap/cache/rabbitevents.php file. The RabbitEventsServiceProvider will automatically use this file instead of scanning the directory.
To clear the cache, use the rabbitevents:clear command:
php artisan rabbitevents:clear
Important
You should run rabbitevents:cache during your deployment process.
Supervisor Configuration
The Supervisor configuration is similar to Laravel Queue. We decided not to copy this doc here.
Logging
The package provides 2 ways to see what happens to your listener. By default, it writes processing, processed, failed messages, and occurred exceptions to console output. The message includes service, event, and listener name. To get the exception's trace, run the listener with verbosity >= 1, for example, -v.
If you want to turn this feature off, just run the listener with the --quiet option.
The package also supports your application logger. To use it, set config value rabbitevents.logging.enabled to true and choose a log level.
When choosing to use the application logger, you may configure the package's logging channel using the config value rabbitevents.logging.channel. By default, it will use the value from logging.default.
rabbitevents/listener 适用场景与选型建议
rabbitevents/listener 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 12.36k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2022 年 02 月 16 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「queue」 「events」 「rabbitmq」 「listener」 「AMQP」 「messaging」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 rabbitevents/listener 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 rabbitevents/listener 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 rabbitevents/listener 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Work with RabbitMQ in Laravel.
Microservice RPC through message queues.
PHP AMQP Binding Library
Библиотека для реализаций паттерна Pub/Sub
A Laravel package to monitor queue jobs.
Wireless Cross-Component Communication
统计信息
- 总下载量: 12.36k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 9
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2022-02-16