rabbitevents/listener

RabbitEvents 库的监听器组件。

v8.2.1 2024-04-29 10:52 UTC

README

RabbitEvents 监听器组件提供了一个 API,用于处理应用程序结构跨发布的各种事件。更多信息请参考 Nuwber 的 RabbitEvents 文档

如果您只需要处理事件,您可以使用 RabbitEvents 的 Listener 与主库分开使用。

目录

  1. 通过 Composer 安装
  2. 配置
  3. 注册监听器
  4. 定义监听器
  5. 中间件
  6. 停止事件的传播
  7. 控制台命令
  8. 日志记录

通过 Composer 安装

RabbitEvents 监听器可以通过 Composer 包管理器安装

composer require rabbitevents/listener

安装监听器后,您可以执行 rabbitevents:install Artisan 命令,该命令将 RabbitEvents 配置文件和 RabbitEventsServiceProvider 安装到您的应用程序中

php artisan rabbitevents:install

配置

有关配置的详细信息,请参阅库的 文档

注册监听器

RabbitEventsServiceProviderlisten 属性包含一个数组,其中包含所有事件(键)及其监听器(值)。您可以添加任意多个事件到这个数组中,以满足您应用程序的需求。

您甚至可以使用 * 作为通配符参数来注册监听器,这允许您使用相同的监听器捕获多个事件。通配符监听器将事件名称作为其第一个参数,将整个事件数据数组作为其第二个参数。

<?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
        ]
    ];
}

定义监听器

事件监听器通过在 $listen 定义中提供的函数接收事件数据。如果没有提供方法,将调用 handle 方法。在 handle 方法内部,您可以执行响应事件所需的必要操作

事件监听器类的示例

<?php

class SendNotification
{
    public function handle($eventPayload)
    {
        Mailer::to(Arr::get($eventPayload, 'user.email'))
            ->subject('Payment Succeeded')
            ->message('...');
    }
}

通配符事件监听器类的示例

<?php

class AllItemEventsListener
{
    public function handle($event, $payload)
    {
        match($event) => [
            'item.created' => ...,
            'item.deleted' => ...,
            'item.updated' => ...,
        ];
    }
}

中间件

监听器中间件允许您在监听器的执行过程中包装自定义逻辑,从而减少了处理程序中的样板代码。例如,您有一个 charge.succeeded 事件,可以在多个 API 中处理,但仅当这笔付款是为特定实体时。

如果没有中间件,您必须在监听器的 handle 方法中检查实体类型。

<?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();
}

如果您只有一个监听器,那么如果许多监听器必须在 handle 方法的第一行执行相同的检查,代码将会变得有些嘈杂。

而不是在每个监听器的开始处编写相同的检查,您可以定义一个处理实体类型的监听器中间件。

<?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';
    }
}

在这个示例中,您可以看到如果您需要停止传播,只需返回 false

创建监听器中间件后,可以通过从监听器的 middleware 方法返回它们或将它们作为 $middleware 属性的数组项来将其附加到监听器上。

<?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';  
    }
}

您还可以指定应调用附加中间件类的哪个方法。

这只是说明您可以将中间件传递给监听器的方式。您可以选择您喜欢的任何方式。

停止事件的传播

有时,您可能希望阻止事件传播到其他监听器。您可以通过从监听器的处理方法中返回 false 来实现这一点。

控制台命令

命令 rabbitevents:listen

这是一个将事件注册到RabbitMQ中的命令

php artisan rabbitevents:listen event.name --memory=512 --tries=3 --sleep=5 -v

此命令在RabbitMQ中注册一个绑定到事件的独立队列。由于 rabbitevents:listen 注册队列,您应该在开始发布事件之前运行此命令。如果您首先发布事件,则不会发生任何操作,但如果没有运行此命令,则监听器将无法处理事件。

要监听应用程序中注册的所有事件,您可以不指定任何事件名称运行

php artisan rabbitevents:listen

或者用逗号分隔事件

php artisan rabbitevents:listen event.one,event.two,event.n

如果事件列表太长,队列名称将作为长队列名称的MD5校验和创建。这是由于AMQP驱动程序不接受较长的名称而实现的。

您只能通过使用 rabbitevents:listen 命令来开始监听事件,因此您可以使用例如 Supervisor

pm2 来控制您的监听器。

如果您的监听器崩溃,则管理器将重新运行您的监听器,并且所有发送到队列的消息都将按发送顺序处理。存在一个已知问题:由于队列是分开的,并且您有影响相同实体的消息,因此不能保证所有操作都将按预期顺序完成。为了避免此类问题,您可以将消息时间作为有效负载的一部分发送,并在您的监听器内部进行处理。

选项

--service= - 默认情况下,它是 config('app.name')。当队列启动时,服务名称成为队列名称的一部分: service:event.name。您可以通过此选项覆盖队列名称的第一部分。
--memory=128 - 内存限制(以兆字节为单位)。如果超过限制,RabbitEvents 将重新启动工作进程。
--timeout=60 - 每条消息被允许处理的时间长度(以秒为单位)。
--tries=1 - 在记录失败之前尝试处理消息的次数。
--sleep=5 - 工作进程在尝试处理失败消息之前等待的秒数。
--quiet - 隐藏控制台输出。
-v - 详细度。为异常启用堆栈跟踪。

命令 rabbitevents:list

要获取所有注册事件的列表,请使用 rabbitevents:list 命令。

php artisan rabbitevents:list

Supervisor 配置

Supervisor 配置类似于 Laravel Queue。我们决定在此处不复制此文档。

日志记录

此包提供了两种查看监听器发生情况的方法。默认情况下,它将 processingprocessedfailed 消息和发生的异常写入控制台输出。消息包括服务、事件和监听器名称。要获取异常的跟踪,请以详细度 >= 1 运行监听器,例如,-v
如果您想关闭此功能,只需以 --quiet 选项运行监听器即可。

此包还支持您的应用程序日志记录器。要使用它,将配置值 rabbitevents.logging.enabled 设置为 true 并选择一个日志级别。

在选择使用应用程序日志记录器时,您可以使用配置值 rabbitevents.logging.channel 配置包的日志记录通道。默认情况下,它将使用 logging.default 的值。