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 2

1 ответ:

Horizon собирает любые тегидо того, как даже помещает задание в очередь, поэтому мы не можем полагаться на какие-либо значения, которые задание не знает до его выполнения. В этом случае задание знает User и Post, потому что мы передаем их для инициализации события.

Для прослушивателей в очереди система тегов проверяет наличие тегов как в объекте события, так и в классе прослушивателя. Как описано в вопросе, невозможно установить теги с динамическими данными на прослушивателе, потому что обработчик выполняет после Horizon выводит задание из очереди. Мы можем только объявить статические теги на прослушивателе, которые Horizon объединит* с тегами на событии:

class PostWasCreatedNotificationSend implements ShouldQueue 
{
    ...
    public function tags() 
    {
        return [ 'listener:' . static::class, 'category:posts' ];
    }
}

С помощью объекта event Horizon пытается автоматически генерировать теги для любых красноречивых членов модели. Например, Horizon создаст следующие теги для события PostWasCreated:

  • $event->userApp\User:<id>
  • $event->postApp\Post:<id>

Мы можем переопределить это поведение и указать Horizon, какие теги устанавливать для события путем определения метода tags(), как указано выше:

class PostWasCreated 
{
    ...
    public function tags() 
    {
        return [ 'post:' . $this->post->id ];
    }
}

Обратите внимание, что на момент написания статьи Horizon не будет автоматически создавать теги для моделей, если событие или прослушиватель предоставляет теги вручную.

Проблема в том, что $this->queueTags никогда не назначается, поэтому в Horizon нет тегов для этого слушателя в очереди... (хотя имя очереди появляется, но нам также нужны теги).

Horizon не создает теги для каждого свойства; автоматический тегирование работает только для тех, которые содержат красноречивые модели (и, как правило, не для слушателя).


*Если событие также используется для трансляции (оно реализует ShouldBroadcast), дополнительное задание, созданное для публикации сообщения, не наследует никакие теги, предоставленные слушателем.