-
Notifications
You must be signed in to change notification settings - Fork 658
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[5.x] Add ability to clear queues from dashboard #890
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -145,6 +145,7 @@ svg.icon { | |
} | ||
|
||
button:hover { | ||
.fill-danger, | ||
.fill-primary { | ||
fill: #fff; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
|
||
namespace Laravel\Horizon\Http\Controllers; | ||
|
||
use Illuminate\Http\Request; | ||
use Illuminate\Queue\QueueManager; | ||
use Illuminate\Support\Arr; | ||
use Laravel\Horizon\Repositories\RedisJobRepository; | ||
|
||
class QueueClearController extends Controller | ||
{ | ||
/** | ||
* Clear the specified queue. | ||
* | ||
* @param \Laravel\Horizon\Repositories\RedisJobRepository $jobRepository | ||
* @param \Illuminate\Queue\QueueManager $manager | ||
* @param \Illuminate\Http\Request $request | ||
* @return void | ||
*/ | ||
public function __invoke(RedisJobRepository $jobRepository, QueueManager $manager, Request $request) | ||
{ | ||
$jobRepository->purge($queue = $request->input('queue')); | ||
|
||
$connection = Arr::first(config('horizon.defaults'))['connection'] ?? 'redis'; | ||
$manager->connection($connection)->clear($queue); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -688,6 +688,27 @@ public function deleteFailed($id) | |
$this->connection()->del($id); | ||
} | ||
|
||
/** | ||
* Delete pending and reserved jobs for a queue. | ||
* | ||
* @param string $queue | ||
* @return void | ||
*/ | ||
public function purge($queue) | ||
{ | ||
$ids = collect(range(0, ceil($this->nextJobId() / 50)))->transform(function ($_, $index) use ($queue) { | ||
return $this->getRecent($index === 0 ? null : $index * 50)->filter(function ($recent) use ($queue) { | ||
return in_array($recent->status, ['pending', 'reserved']) && $recent->queue === $queue; | ||
}); | ||
})->flatten(1)->pluck('id')->all(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please explain what this is doing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we're collecting the IDs of the pending or reserved jobs on the specified queue. To do so, we get all the recent jobs (50 at a time based on the in-built RedisJobRepository methods) and filter through them to check 1) if they're either pending or reserved and 2) if the queue matches the specified queue. On the filtered set of jobs, we pluck the job IDs and then delete them from the Redis hash and recent/pending jobs sorted sets. |
||
|
||
$this->connection()->pipeline(function ($pipe) use ($ids) { | ||
$pipe->zrem('recent_jobs', $ids); | ||
$pipe->zrem('pending_jobs', $ids); | ||
$pipe->del($ids); | ||
}); | ||
} | ||
|
||
/** | ||
* Get the Redis connection instance. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
|
||
namespace Laravel\Horizon\Tests\Controller; | ||
|
||
use Laravel\Horizon\RedisQueue; | ||
use Laravel\Horizon\Repositories\RedisJobRepository; | ||
use Mockery; | ||
|
||
class QueueClearControllerTest extends AbstractControllerTest | ||
{ | ||
public function test_it_removes_all_job_from_specific_queue() | ||
{ | ||
Mockery::mock(RedisJobRepository::class) | ||
->shouldReceive('purge') | ||
->withArgs(['email-processing']); | ||
|
||
Mockery::mock(RedisQueue::class) | ||
->shouldReceive('clear') | ||
->withArgs(['email-processing']); | ||
|
||
$this->actingAs(new Fakes\User) | ||
->post('/horizon/api/clearQueue', ['queue' => 'email-processing']); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unclear to me why a delete operation would be a POST. Shouldn't it be something like DELETE /queues/{queue-name} or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought of clearing queues as more of an action rather than deleting a resource. If you'd like I can change it to a delete operation.