laravel / ideas

Issues board used for Laravel internals discussions.
938 stars 28 forks source link

Allow one or more listeners to be queued or broadcasted if the whole event is not queued already. #1259

Open morloderex opened 6 years ago

morloderex commented 6 years ago

Right now you when you specify that an event should be queued or broadcasted. All of it's listeners are queued and broadcasted.

But in certain situations where an event is not queued or broadcasted you might still need one specific listener to still be queued or broadcasted.

For instance, i have events that should be fired instantly and http calls that should happen.

I would like to queue my http calls. But still have the other listeners fire instantly. Right now for this to happen i would have to create a whole new event and dispatch that on to the queue to allow for this. I don't really see why this should be necessary.

I propose a change to the listeners to allow them to be broadcasted or queued in the situations where the whole event is not queued or broadcasted already.

What do you think abou this idea?

Miguel-Serejo commented 6 years ago

I may be misunderstanding your use case, but it sounds like what you want to do is emit new queued events from your listeners in some cases, which should just work.

morloderex commented 6 years ago

I do know that i can do that.

But i find it a bit tidious to do, i would like to be able just to simply add the interfaces for queueing or broadcasting like on an event and have laravel take care of the rest.

Miguel-Serejo commented 6 years ago

I'm not sure I quite understand what you're proposing. Please correct me if I'm misinterpreting your use case here. This is my current understanding of what you're describing:

If that's what you're after, how do you propose the queue handler determine where to "pick up" the processing of the event?

Could you maybe provide a small sample code demonstrating what your listener would look like?

morloderex commented 6 years ago

@36864 Oh yes sure. Imagine that you this.


dispatch(new Someevent())`

['listenersForSomeEvent' => [
    synchronousTask::class,
    QueuedTask::class
]

class QueuedTask impliments ShouldQueue {

      use Queueable;

      public function handle($event) {
           // this should do something on the queue.
      }

      public function beforeQueue($event):
     {
           // this get called right before the dispatch of the job with this single listener takes place.
           // do some work before adding me on the queue. like refresh the models or collection.
     }

     public function afterQueue($event): listenersForSomeEvent 
     {
           // this get called right after the dispatch of the job with this single listener takes place.
           // do some work after my task/job on the queue has finished. like refresh the models or collection.
     }
}

class synchronousTask {

    public function handle()
    {
          // this is handled instantly.
    }
}

Because the listener QueuedTask impliments ShouldQueue It should run this task with the event through the queue when doing so it should pass the event with it.

The listeners will still get called from the top the the bottom but synchronous tasks gets called first then all the listeners that should be queued or broadcasted.

We have 2 new methods that should be called on the listener afterHandle is the important one it should have received any data from the queue and then we should update the event with the new data given from that job.

Miguel-Serejo commented 6 years ago

Personally I would prefer to have two different jobs for what needs to be queued and what doesn't, but I can see how this would be useful in some cases.

This should probably be implemented as a trait rather than adding it to the interface, so we don't force everyone to implement those two methods if they're not gonna need them.