From 2b9d596bdd9340e87f0e18d5319bf0adc774451d Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Fri, 1 Dec 2023 03:21:51 +0800 Subject: [PATCH] [10.x] Fixes retrying failed jobs causes PHP memory exhaustion errors when dealing with thousands of failed jobs (#49186) * [10.x] Fixes retrying failed jobs causes PHP memory exhaustion errors when dealing with thousands of failed jobs fixes laravel/framework#49185 Signed-off-by: Mior Muhammad Zaki * Apply fixes from StyleCI * formatting --------- Signed-off-by: Mior Muhammad Zaki Co-authored-by: StyleCI Bot Co-authored-by: Taylor Otwell --- src/Illuminate/Queue/Console/RetryCommand.php | 18 +++++++++++++----- .../Queue/Failed/DatabaseFailedJobProvider.php | 15 +++++++++++++++ .../Failed/DatabaseUuidFailedJobProvider.php | 15 +++++++++++++++ .../Queue/Failed/DynamoDbFailedJobProvider.php | 14 ++++++++++++++ .../Failed/FailedJobProviderInterface.php | 3 +++ .../Queue/Failed/FileFailedJobProvider.php | 14 ++++++++++++++ .../Queue/Failed/NullFailedJobProvider.php | 11 +++++++++++ 7 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Queue/Console/RetryCommand.php b/src/Illuminate/Queue/Console/RetryCommand.php index 37827dd01683..13640feb4efb 100644 --- a/src/Illuminate/Queue/Console/RetryCommand.php +++ b/src/Illuminate/Queue/Console/RetryCommand.php @@ -70,7 +70,11 @@ protected function getJobIds() $ids = (array) $this->argument('id'); if (count($ids) === 1 && $ids[0] === 'all') { - return Arr::pluck($this->laravel['queue.failer']->all(), 'id'); + $failer = $this->laravel['queue.failer']; + + return method_exists($failer, 'ids') + ? $failer->ids() + : Arr::pluck($failer->all(), 'id'); } if ($queue = $this->option('queue')) { @@ -92,10 +96,14 @@ protected function getJobIds() */ protected function getJobIdsByQueue($queue) { - $ids = collect($this->laravel['queue.failer']->all()) - ->where('queue', $queue) - ->pluck('id') - ->toArray(); + $failer = $this->laravel['queue.failer']; + + $ids = method_exists($failer, 'ids') + ? $failer->ids($queue) + : collect($failer->all()) + ->where('queue', $queue) + ->pluck('id') + ->toArray(); if (count($ids) === 0) { $this->components->error("Unable to find failed jobs for queue [{$queue}]."); diff --git a/src/Illuminate/Queue/Failed/DatabaseFailedJobProvider.php b/src/Illuminate/Queue/Failed/DatabaseFailedJobProvider.php index 4da8c0337c2f..49cb3b98ae9a 100644 --- a/src/Illuminate/Queue/Failed/DatabaseFailedJobProvider.php +++ b/src/Illuminate/Queue/Failed/DatabaseFailedJobProvider.php @@ -64,6 +64,21 @@ public function log($connection, $queue, $payload, $exception) )); } + /** + * Get the IDs of all of the failed jobs. + * + * @param string|null $queue + * @return array + */ + public function ids($queue = null) + { + return $this->getTable() + ->when(! is_null($queue), fn ($query) => $query->where('queue', $queue)) + ->orderBy('id', 'desc') + ->pluck('id') + ->all(); + } + /** * Get a list of all of the failed jobs. * diff --git a/src/Illuminate/Queue/Failed/DatabaseUuidFailedJobProvider.php b/src/Illuminate/Queue/Failed/DatabaseUuidFailedJobProvider.php index f51c46f571b0..b3192f246beb 100644 --- a/src/Illuminate/Queue/Failed/DatabaseUuidFailedJobProvider.php +++ b/src/Illuminate/Queue/Failed/DatabaseUuidFailedJobProvider.php @@ -67,6 +67,21 @@ public function log($connection, $queue, $payload, $exception) return $uuid; } + /** + * Get the IDs of all of the failed jobs. + * + * @param string|null $queue + * @return array + */ + public function ids($queue = null) + { + return $this->getTable() + ->when(! is_null($queue), fn ($query) => $query->where('queue', $queue)) + ->orderBy('id', 'desc') + ->pluck('uuid') + ->all(); + } + /** * Get a list of all of the failed jobs. * diff --git a/src/Illuminate/Queue/Failed/DynamoDbFailedJobProvider.php b/src/Illuminate/Queue/Failed/DynamoDbFailedJobProvider.php index 2feeaa98a29f..226c752e94ef 100644 --- a/src/Illuminate/Queue/Failed/DynamoDbFailedJobProvider.php +++ b/src/Illuminate/Queue/Failed/DynamoDbFailedJobProvider.php @@ -78,6 +78,20 @@ public function log($connection, $queue, $payload, $exception) return $id; } + /** + * Get the IDs of all of the failed jobs. + * + * @param string|null $queue + * @return array + */ + public function ids($queue = null) + { + return collect($this->all()) + ->when(! is_null($queue), fn ($collect) => $collect->where('queue', $queue)) + ->pluck('id') + ->all(); + } + /** * Get a list of all of the failed jobs. * diff --git a/src/Illuminate/Queue/Failed/FailedJobProviderInterface.php b/src/Illuminate/Queue/Failed/FailedJobProviderInterface.php index 26dd583b9496..bb52d1749ada 100644 --- a/src/Illuminate/Queue/Failed/FailedJobProviderInterface.php +++ b/src/Illuminate/Queue/Failed/FailedJobProviderInterface.php @@ -2,6 +2,9 @@ namespace Illuminate\Queue\Failed; +/** + * @method array ids(string $queue = null) + */ interface FailedJobProviderInterface { /** diff --git a/src/Illuminate/Queue/Failed/FileFailedJobProvider.php b/src/Illuminate/Queue/Failed/FileFailedJobProvider.php index f79efc05f39f..43f43248deb1 100644 --- a/src/Illuminate/Queue/Failed/FileFailedJobProvider.php +++ b/src/Illuminate/Queue/Failed/FileFailedJobProvider.php @@ -78,6 +78,20 @@ public function log($connection, $queue, $payload, $exception) }); } + /** + * Get the IDs of all of the failed jobs. + * + * @param string|null $queue + * @return array + */ + public function ids($queue = null) + { + return collect($this->all()) + ->when(! is_null($queue), fn ($collect) => $collect->where('queue', $queue)) + ->pluck('id') + ->all(); + } + /** * Get a list of all of the failed jobs. * diff --git a/src/Illuminate/Queue/Failed/NullFailedJobProvider.php b/src/Illuminate/Queue/Failed/NullFailedJobProvider.php index a086134c98f3..f92c59eba658 100644 --- a/src/Illuminate/Queue/Failed/NullFailedJobProvider.php +++ b/src/Illuminate/Queue/Failed/NullFailedJobProvider.php @@ -18,6 +18,17 @@ public function log($connection, $queue, $payload, $exception) // } + /** + * Get the IDs of all of the failed jobs. + * + * @param string|null $queue + * @return array + */ + public function ids($queue = null) + { + return []; + } + /** * Get a list of all of the failed jobs. *