Laravel 5.5-пользовательские теги заданий Horizon для прослушивателя событий в очереди
В документации для Horizon упоминается, что пользовательские теги могут быть добавлены к прослушивателям событий в очереди. Тем не менее, я не могу найти способ вытащить мой экземпляр события, содержащий необходимые мне данные. Приведенный пример использует намек на тип для извлечения соответствующей модели из контейнера службы и присваивает ее переменной экземпляра в конструкторе, а затем использует эту переменную экземпляра в методе tags()
для получения данных о конкретном экземпляре модели, с которым выполняется операция.
Когда однако это не работает в прослушивателе событий в очереди. На самом деле конструктор никогда не вызывается вообще, из-за того, что модель сериализуется и "повторно гидратируется", когда она приходит к выполнению. Таким образом, тип-намек в конструкторе ничего не делает, и tags()
, кажется, вызывается раньше handle()
, поэтому я не могу получить доступ к объекту события, который я слушаю.
Кто-нибудь знает, как я могу получить информацию о событии в теге в этом ситуация?
Обновление:
Событие, вызванное контроллером:
event(new PostWasCreated($user, $post));
Событие PostWasCreated :
<?php
namespace AppEvents;
use IlluminateBroadcastingChannel;
use IlluminateQueueSerializesModels;
use IlluminateBroadcastingPrivateChannel;
use IlluminateBroadcastingPresenceChannel;
use IlluminateBroadcastingInteractsWithSockets;
use IlluminateContractsBroadcastingShouldBroadcast;
use AppUser;
use AppPost;
class PostWasCreated
{
use InteractsWithSockets, SerializesModels;
public $user;
public $post;
public function __construct(User $user, Post $post)
{
$this->user = $user;
$this->post = $post;
}
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
Слушатель PostWasCreatedNotificationSend :
<?php
namespace AppListeners;
use AppEventsPostWasCreated;
use IlluminateQueueInteractsWithQueue;
use IlluminateContractsQueueShouldQueue;
class PostWasCreatedNotificationSend implements ShouldQueue
{
protected $event;
public $queue = 'notifications'; // Adds queue name
public function __construct(PostWasCreated $event)
{
$this->event = $event;
// Does NOT add queue tag
$this->queueTags = ['post: ' . $this->event->post->id];
}
public function tags()
{
return $this->queueTags;
}
public function handle(PostWasCreated $event)
{
// handle event here...
}
}
Проблема в том, что $this->queueTags
никогда не назначается, поэтому в Horizon нет тегов для этого слушателя в очереди... (хотя имя очереди появляется, но нам также нужны теги).
1 ответ:
Horizon собирает любые тегидо того, как даже помещает задание в очередь, поэтому мы не можем полагаться на какие-либо значения, которые задание не знает до его выполнения. В этом случае задание знает
User
иPost
, потому что мы передаем их для инициализации события.Для прослушивателей в очереди система тегов проверяет наличие тегов как в объекте события, так и в классе прослушивателя. Как описано в вопросе, невозможно установить теги с динамическими данными на прослушивателе, потому что обработчик выполняет после Horizon выводит задание из очереди. Мы можем только объявить статические теги на прослушивателе, которые Horizon объединит* с тегами на событии:
class PostWasCreatedNotificationSend implements ShouldQueue { ... public function tags() { return [ 'listener:' . static::class, 'category:posts' ]; } }
С помощью объекта event Horizon пытается автоматически генерировать теги для любых красноречивых членов модели. Например, Horizon создаст следующие теги для события
PostWasCreated
:
$event->user
→App\User:<id>
$event->post
→App\Post:<id>
Мы можем переопределить это поведение и указать Horizon, какие теги устанавливать для события путем определения метода
tags()
, как указано выше:class PostWasCreated { ... public function tags() { return [ 'post:' . $this->post->id ]; } }
Обратите внимание, что на момент написания статьи Horizon не будет автоматически создавать теги для моделей, если событие или прослушиватель предоставляет теги вручную.
Проблема в том, что
$this->queueTags
никогда не назначается, поэтому в Horizon нет тегов для этого слушателя в очереди... (хотя имя очереди появляется, но нам также нужны теги).Horizon не создает теги для каждого свойства; автоматический тегирование работает только для тех, которые содержат красноречивые модели (и, как правило, не для слушателя).
*Если событие также используется для трансляции (оно реализует
ShouldBroadcast
), дополнительное задание, созданное для публикации сообщения, не наследует никакие теги, предоставленные слушателем.