в документация для Horizon, упоминается, что пользовательские теги могут быть добавлены в прослушиватели событий в очереди. Тем не менее, я не могу найти способ получить экземпляр моего события, содержащий нужные мне данные. В приведенном примере используется подсказка типа, чтобы вытащить соответствующую модель из контейнера службы и назначить ее переменной экземпляра в конструкторе, а затем использовать эту переменную экземпляра в tags()
метод для получения данных о конкретном экземпляре модели, на котором выполняется операция.
Когда это делается в очереди событий, это не работает. На самом деле, конструктор, кажется, никогда не вызывается вообще, потому что модель сериализуется и «гидратируется», когда дело доходит до выполнения. Так что подсказка типа в конструкторе ничего не делает, и tags()
кажется, вызывается раньше handle()
, поэтому я не могу получить доступ к объекту события, который слушаю.
Кто-нибудь знает, как я могу получить информацию о событии в теге в этой ситуации?
Обновить:
Событие вызвано в контроллере:
event(new PostWasCreated($user, $post));
Событие PostWasCreated:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\User;
use App\Post;
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 App\Listeners;
use App\Events\PostWasCreated;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
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 для этого прослушивателя в очереди нет тегов … (хотя имя очереди отображается, но нам также нужны теги).
Horizon собирает любые метки до даже помещая задание в очередь, поэтому мы не можем полагаться ни на какие значения, которые задание не знает до его выполнения. В этом случае работа знает User
а также Post
потому что мы передаем их для инициализации события.
Для слушателей, находящихся в очереди, система тегов проверяет теги как для объекта события, так и для класса слушателя. Как описано в вопросе, нет способа установить теги с динамическими данными на слушателе, потому что обработчик выполняет после Горизонт вытаскивает работу из очереди. Мы можем только объявить статические теги на слушателе, что Horizon объединит * с тегами на событии:
class PostWasCreatedNotificationSend implements ShouldQueue
{
...
public function tags()
{
return [ 'listener:' . static::class, 'category:posts' ];
}
}
С помощью объекта события Horizon пытается автоматически сгенерировать теги для любых членов модели Eloquent. Например, 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 не создает теги для каждого свойства; автоматическая пометка работает только для тех, которые содержат модели Eloquent (и, как правило, не для слушателя).
* Если событие также используется для трансляции (оно реализует ShouldBroadcast
), дополнительное задание, созданное для публикации сообщения, не наследует никаких тегов, предоставленных слушателем.
Других решений пока нет …