我想确保在上一个事件之后短时间内(约5秒)内发生的事件继续延迟广播,直到该时间段内没有触发新事件。期望的效果是在定义的时间段内没有调度新事件之后仅发送一个广播。 示例:2 秒内创建 100 个新实例。只有在另外 5 秒内没有创建新实例后,才应发送广播。
-> 将 laravel-10 与 php-8.2 和 mariadb-10 一起使用
每次在模型的 boot() 方法中创建新实例时,我都使用模型观察器来调度事件:
static::created(function ($notification) {
event(
new FrontendNotificationEvent(
$notification->user_id, 'update_notifications'
)
);
});
在 FrontendNotificationEvent 类中,我使用 uniqueId() 实现 ShouldBeUnique,以一次仅允许每个 eventName/userId 组合的一个事件。队列配置为使用“数据库”驱动程序。
namespace App\Events;
use Carbon\Carbon;
use Illuminate\Broadcasting\BroadcastEvent;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBeUnique;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class FrontendNotificationEvent implements ShouldBeUnique, ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(private readonly string $userId, public string $userEventName, public array $payload = [])
{
$this->payload['timestamp'] = Carbon::now();
}
public function broadcastOn(): Channel
{
return new PrivateChannel(USER_EVENTS_CHANNEL_PREFIX . $this->userId);
}
public function broadcastAs(): string
{
return $this->userEventName;
}
public function uniqueId() {
return '_' . $this->broadcastAs() . '-' . $this->userId;
}
}
我尝试了在 FrontendNotificationEvent 中设置延迟和/或 uniqueFor 变量的一些组合:
public int $delay = 5;
public int $uniqueFor = 5;
我只能实现第一个广播被发送并抑制后续广播,但我希望第一个广播被延迟,直到5秒内没有新的广播进来。
如果需要任何说明,请告诉我。
经过更多的挖掘和尝试,我创建了一个单独的作业,它是独特的且延迟的:
static::created(function ($notification) {
// Dispatch a unique and delayed Job to send a notification. Since the job is unique, no additional notifications will be queued while it is delayed
// [WARNING] The uniqueness does not seem to work with the "array" CACHE_DRIVER!
UserEventNotificationJob::dispatch(
$notification->user_id,
'update_notifications'
)->delay(now()->addSeconds(USER_EVENT_NOTIFICATIONS_MAX_EVERY_SECONDS));
});
class UserEventNotificationJob implements ShouldBeUnique, ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(
public string $userId,
public string $userEventName
) {
}
public function handle(): void
{
event(new UserEventNotificationBroadcastEvent($this->userId, $this->userEventName, $this->uniqueId()));
}
public function uniqueId(): string
{
return $this->userEventName . '_' . $this->userId;
}
}