Skip to content

Conversation

@jackbayliss
Copy link
Contributor

@jackbayliss jackbayliss commented Dec 11, 2025

Currently, queue routing in Laravel requires each job, notification, or mailable to explicitly define its queue (e.g. via a $queue property or viaQueues() etc) or extend/ implement / use a class that has it defined, As a result, queue configuration often becomes repetitive and scattered across multiple classes.

I tried a basic version of this via #57712 but, Taylor rightly said the DX was off so this is a re-attempt.

This PR introduces a way to register default queues / connection effectively "route" it, based on a queueable object’s class, parent class, interface, or trait

This is my mind has a few use cases:

  • Less repetition - no need to set the queue/connection property or have to remember to extend something.
  • Third party packages: Route package traits/classes without modifying them
  • Central config: See all queue routing in one place (such as the AppServiceProvider)
  • Easier environment specific queues: Different queues per environment easily

Defaults can be routed via the Queue manager / Facade:

This allows you to do:

Queue::route(Foo::class, connection: 'foo', queue: 'bar');

// or even do multiple at once  - Based on the parent class , trait used etc.

Queue::route([
    Foo::class => ['connection-2', 'elevated-queue'], // connection and queue specified..
    Bar::class => 'queue', // default connection
]);

You can pass in a class, interface, or trait and if the queued class is, extending / implementing or using the class it'll set the default queue / connection to what the user has set. I don't believe it's BC as it's only called if the original queue parameter is null - and anything else ie viaQueues still takes precedent.

I've targeted 13.x as it's introduced a new trait - and feels like a big change for a patch release.

Method names etc open to changing.

@github-actions
Copy link

Thanks for submitting a PR!

Note that draft PR's are not reviewed. If you would like a review, please mark your pull request as ready for review in the GitHub user interface.

Pull requests that are abandoned in draft may be closed due to inactivity.

@browner12
Copy link
Contributor

How would this handle things like Notifications where you can define multiple queues inside the class depending on the channel (mail, db, slack, etc) it is delivering to?

@jackbayliss
Copy link
Contributor Author

jackbayliss commented Dec 12, 2025

@browner12 Thanks for your reply! 🙇 For Notifications do you mean like viaQueues? If they've defined viaQueues that will continue to take precedence, so this wouldn't override it as that's explicitly set on the class. (This is just mainly for classes where its not specifically set, so no B/C)

Details
                $queue = $notification->queue ?? $this->manager->resolveDefaultQueue($notification); // this is the new stuff it checks if they've set the default the new way

                if (method_exists($notification, 'viaQueues')) {
                    $queue = $notification->viaQueues()[$channel] ?? $queue;
                }

@shaedrich
Copy link
Contributor

Is this really a default if it doesn't apply for all jobs/job types but only specific classes? Can't the base classes (e.g. abstract classes, traits, etc.) define them themselves?

If you want to see all of them, wouldn't an artisan command make more sense?

@jackbayliss
Copy link
Contributor Author

jackbayliss commented Dec 13, 2025

@shaedrich Yeah, I guess they could but..

  • For third-party packages, you can't modify their traits/base classes, so this lets you route them without touching vendor code
  • It feels clear, so you could do it in the app service provider and it's clear whats going where - IE new people, anyone can clearly see what's going where, no picking through abstracts / traits etc.
  • Environment-specific queuing becomes easy (production vs local might need different queues)

(I've added this to the main description, as I realise it wasn't the clearest 👍🏻 )

@shaedrich
Copy link
Contributor

shaedrich commented Dec 13, 2025

  • For third-party packages, you can't modify their traits/base classes, so this lets you route them without touching vendor code

But you could extend said classes

It feels clear, so you could do it in the app service provider and it's clear whats going where - IE new people, anyone can clearly see what's going where, no picking through abstracts / traits etc.

It gets these information to one point but takes them away from the classes where the apply to. When you change these classes, you then have to think about changing the service provider as well. Just like with morph maps.

But your addition might sure be helpful to some 👍🏻

rename trait to follow the actual singleton name

more tweaks
@jackbayliss jackbayliss changed the title [13.x] Add default queue assignment by class type [13.x] Add ability to default queue by class type Dec 15, 2025
dont think we need it
@jackbayliss
Copy link
Contributor Author

Marking this for review to see if this might be of interest. If not, no problem. 🫡

@jackbayliss jackbayliss marked this pull request as ready for review December 15, 2025 15:58
no point returning this, not planning on chaining it
@taylorotwell
Copy link
Member

taylorotwell commented Dec 28, 2025

I do like the overall idea here. Will try to review soon. I think I would call it something like Queue::route since you are routing jobs of various types to different queues.

@taylorotwell
Copy link
Member

taylorotwell commented Jan 8, 2026

@jackbayliss I'm curious if this is missing a couple of things.

First, queued event listeners. We queue jobs for these in the event dispatcher. Right now it doesn't seem like you can route these by listener class name in Queue::route(). Secondly, and maybe not as important, queued jobs for broadcasted events.

@jackbayliss jackbayliss marked this pull request as draft January 8, 2026 21:38
@jackbayliss
Copy link
Contributor Author

@taylorotwell I'll have a poke about, I'll draft for now and open once I think it's ready for a re-review - thanks for your time on this.

@taylorotwell
Copy link
Member

@jackbayliss I'm fixing it now.

@taylorotwell taylorotwell marked this pull request as ready for review January 8, 2026 21:44
@jackbayliss
Copy link
Contributor Author

@taylorotwell Cheers thank you!

@taylorotwell
Copy link
Member

@jackbayliss I've added support for broadcast events and queued listeners.

Need help: I've updated the Queue::route API so you can route connections like:

Queue::route([
    Foo::class => ['connection', 'queue'],
    Bar::class => 'queue',
]);

Queue::route(Foo::class, connection: 'foo', queue: 'bar');

Can you update the places we set queue to also set connection everywhere we are using this feature? The trait has a new resolveConnectionFromQueueRoute method you can use.

/**
* Set the queue route for the given class.
*
* @param array|class-string $class
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can type the array as well:

Suggested change
* @param array|class-string $class
* @param array<class-string, string|array{0: string, 1: string}>|class-string $class

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll let Big T decide on that one 👍🏻

@jackbayliss
Copy link
Contributor Author

jackbayliss commented Jan 9, 2026

@taylorotwell Hopefully sorted! or at least closer, presume there will be some formatting tweaks, but let me know if anything else needs tweaking - will be around at some point tomorrow after work. 👍🏻 - Thanks again.

@taylorotwell taylorotwell merged commit 47e8653 into laravel:master Jan 9, 2026
64 checks passed
@taylorotwell
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants