Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Feature/queue pause resume#57800

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

@yousefkadah
Copy link
Contributor

Problem

There is no way to pause a single queue in Laravel.
If you want to stop one queue, you must stopall queue workers — this haltsall queues, not just the one you need to pause.


Solution

Addqueue pause and resume functionality.
Workers will skip paused queues but continue processing other queues.


Queue::pause('emails');Queue::resume('emails');Queue::isPaused('emails');

Artisan Commands

php artisan queue:pause emailsphp artisan queue:resume emailsphp artisan queue:pause:list

How It Works

  • Pause status stored in cache
  • Workers check cache before processing each queue
  • Paused queues are skipped
  • Jobs remain in queue until resumed
  • Works with all queue drivers

Benefits

  • No lost jobs
  • Other queues keep working
  • Simple to use
  • No breaking changes

Example

Queue::pause('emails');// Perform maintenanceQueue::resume('emails');

This feature providesbetter queue control without stopping all workers.

rodrigopedra, sajjadhossainshohag, jackbayliss, jacobmllr95, yousefkadah, PrashantDhungana, bagwaa, ziadoz, MrKacmaz, silviooosilva, and 5 more reacted with thumbs up emojinbreens and ManojKiranA reacted with heart emoji
yousefkadahand others added3 commitsNovember 13, 2025 23:25
This commit introduces a new feature that allows pausing and resuming individual queues without stopping workers, providing granular control over queue processing.Features:- Queue::pause($queue, $ttl) - Pause a specific queue with optional TTL- Queue::resume($queue) - Resume a paused queue- Queue::isPaused($queue) - Check if a queue is paused- Queue::getPausedQueues() - Get list of all paused queuesArtisan Commands:- queue:pause {queue} - Pause a queue- queue:resume {queue} - Resume a queue- queue:pause:list - List all paused queuesImplementation:- Modified Worker to skip paused queues when looking for jobs- Uses cache to track paused queue status with configurable TTL- Works with all queue drivers (Redis, Database, SQS, etc.)- No jobs are lost - they remain in queue until resumed- Fully backwards compatible with existing queue functionalityFiles Modified:- src/Illuminate/Queue/QueueManager.php- src/Illuminate/Queue/Worker.php- src/Illuminate/Foundation/Providers/ArtisanServiceProvider.phpFiles Created:- src/Illuminate/Queue/Console/PauseCommand.php- src/Illuminate/Queue/Console/ResumeCommand.php- src/Illuminate/Queue/Console/PauseListCommand.php- QUEUE_PAUSE_RESUME_FEATURE.md🤖 Generated with [Claude Code](https://claude.com/claude-code)Co-Authored-By: Claude <noreply@anthropic.com>
Update the Factory interface to include the new pause/resume methods.This resolves IDE warnings and provides proper type hints for thequeue pause/resume functionality.🤖 Generated with [Claude Code](https://claude.com/claude-code)Co-Authored-By: Claude <noreply@anthropic.com>
@rodrigopedra
Copy link
Contributor

I have had something like this for years on a project to skip jobs after reaching an API rate limit to avoid attempting several jobs in a row.

It also allows having a worker working on more than one queue while the other one is paused/blocked (in my implementation I call it blocked).

Locally I have a custom queue driver that extends from theDatabaseQueue class and just overrides thepop method to returnnull while the queue is blocked.

And a job middleware to block/pause the queue when a 429 response is caught.

It will be great to have this in the framework.

Also, it is a much more generic solution than mine.

Thanks a lot!

{
$cache =$this->app['cache']->store();

$cache->put("queue_paused:{$queue}",true,$ttl);
Copy link
Contributor

Choose a reason for hiding this comment

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

Operation is not atomic here. In some concurrent situation (pausing two queues same time) threir may be such case:

  • first process getPausedQueues returns []
  • second proccess getPausedQueues returns []
  • first process storePausedQueuesList sets ['queue1']
  • second process storePausedQueuesList sets ['queue2']

finaly queue_paused_list has ['queue2'] and not ['queue1', 'queue2'] as expected.

One way is to use some sort of locks or isolation here.
But maybe it would be better for siplicicty not to provide PauseList functionality at all. Pausing and resuming certain queue (and single isolated cache key) would be enough. Currently framwork does not have any functions to get all existing queues list, so listing just paused queues is redundant.

* @param int $ttl
* @return void
*/
publicfunctionpause($queue,$ttl =86400)
Copy link
Contributor

Choose a reason for hiding this comment

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

Very strange solution to pause just for one day. Why not week, year, or 30 seconds? It's better to pass null as default, meaning by default pausing queue until it's resumed manualy.

For other cases developers still will have a way to pass any ttl they want in certain case


foreach (explode(',',$queue)as$index =>$queue) {
// Skip paused queues
if ($this->isQueuePaused($queue)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider situations, where you have threedefault queue on three different connections. In current solution, trying to pause it, you will pause all three queues, leaving no way to pause just one.

You should take connection name into account too, to point exactly to specific queue.

Copy link
Contributor

@vadimonusvadimonus left a comment

Choose a reason for hiding this comment

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

Interesting idea, but solution has flaws

@taylorotwell
Copy link
Member

I think I would want the ability to pause on both connection and queue with syntax similar to:https://laravel.com/docs/12.x/queues#monitoring-your-queues

php artisan queue:pause redis:default

@taylorotwelltaylorotwell marked this pull request as draftNovember 20, 2025 20:10
@yousefkadah
Copy link
ContributorAuthor

vadimonus

Hi Taylor,

Thank you for the feedback! I've updated the implementation to support theconnection:queue syntax exactly as you suggested.

Changes made:

✅ Commands now acceptconnection:queue format (e.g.,redis:default)
✅ Follows the same pattern asqueue:monitor command
✅ Defaults to the default connection if only queue name is provided

Examples:

php artisan queue:pause redis:defaultphp artisan queue:pause database:emails --ttl=3600php artisan queue:resume redis:default

The implementation uses aparseQueue() method similar toMonitorCommand to handle the parsing. All tests are passing with full connection isolation.

@yousefkadah
Copy link
ContributorAuthor

Interesting idea, but solution has flaws

Hi vadimonus,

Thank you for the detailed code review! I've addressed all three issues you identified:

1. Race Condition ✅

You were absolutely right about the non-atomic operations. I've implemented proper locking usingcache->lock():

$lock =$cache->lock('queue_paused_list_lock',10);try {$lock->block(5);$pausedQueues =$this->getPausedQueues();// ... modify list atomically ...$this->storePausedQueuesList($pausedQueues);}finally {$lock->release();}

This ensures atomic read-modify-write operations and prevents the concurrent modification issue you described.

2. TTL Default Value ✅

Changed from 1 day tonull (indefinite pause) as you suggested:

publicfunctionpause($connection,$queue,$ttl =null){if ($ttl ===null) {$cache->forever("queue_paused:{$connection}:{$queue}",true);    }else {$cache->put("queue_paused:{$connection}:{$queue}",true,$ttl);    }}

The--ttl option is now optional, and developers can specify custom TTL when needed.

3. Connection Name ✅

All methods now include connection name in the cache key:

// Cache key format: queue_paused:{connection}:{queue}queue_paused:redis:defaultqueue_paused:database:emails

This ensures pausingredis:default doesn't affectdatabase:default. The pause list also stores queues inconnection:queue format.

Test Coverage:
14 tests, 40 assertions - all passing ✅

Thank you again for the thorough review!

@yousefkadahyousefkadah marked this pull request as ready for reviewNovember 20, 2025 21:11
@vadimonus
Copy link
Contributor

@yousefkadah , i still do not undertand use cases , where listing of paused queues can bee needed. The declared problem is that's no ability to pause certain queue. This problem is solved well without listing currrently paused queues.

Take a look at mentionned earliermonitor command. It works only with provided as argument list of queues. If someday you decide to extand this command to show if queue it's paused or not,Queue::isQueuePaused would be enougt, and you will not needgetPausedQueues method for it.

You're using cache locks to prevent race condition. Currently Queues does not depends on cache locks feature. Not all cache drivers (do not forget for custom ones) can provide locking feature. Pausing will fail with such drivers.
So feature of listing paused queues gives more questions, than profits. You may allways introduce this later as separate feature, as well as showing paused queues in monitor command.

Let's wait for@taylorotwell , only his opinion is significant here

{
$cache =$this->app['cache']->store();

if ($ttl ===null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

you do not need conditions here, put method already implements forever if ttl=null

@taylorotwell
Copy link
Member

Simplified this a bit to remove the listing stuff and blocking to just get a simpler version of the feature in now while I think about how I want to expose and manage the list.

isaacdew2 reacted with hooray emoji

@taylorotwelltaylorotwell merged commit2dfe64b intolaravel:12.xNov 21, 2025
73 of 74 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

1 more reviewer

@vadimonusvadimonusvadimonus left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

4 participants

@yousefkadah@rodrigopedra@taylorotwell@vadimonus

[8]ページ先頭

©2009-2025 Movatter.jp