diff --git a/src/Commands/QueueRetryCommand.php b/src/Commands/QueueRetryCommand.php new file mode 100644 index 0000000..af8f80a --- /dev/null +++ b/src/Commands/QueueRetryCommand.php @@ -0,0 +1,86 @@ +option('id'); + $manager = app(QueueManager::class); + + if ($id) { + return $this->retryJobById($manager, $id); + } + + FailedJob::query() + ->cursor(function (FailedJob $failedJob) use ($manager) { + $this->retryFailedJob($manager, $failedJob); + }); + + return Command::SUCCESS; + } + + protected function retryJobById(QueueManager $manager, int $id): int + { + $failedJob = FailedJob::find($id); + + if (!$failedJob) { + $this->error("Failed job with ID {$id} not found."); + return Command::FAILURE; + } + + if ($this->retryFailedJob($manager, $failedJob)) { + return Command::SUCCESS; + } + + return Command::FAILURE; + } + + protected function retryFailedJob(QueueManager $manager, FailedJob $failedJob): bool + { + try { + $job = $manager->unserializeJob($failedJob->payload); + $jobClass = get_class($job); + + // Reset attempts + $job->attempts = 0; + + // Push back to queue + $manager->push($job); + + // Delete from failed jobs + $failedJob->delete(); + + $this->info("✔ Retried job [{$jobClass}] (ID: {$failedJob->id})"); + return true; + } catch (\Throwable $e) { + $this->error("✖ Failed to retry job ID {$failedJob->id}: " . $e->getMessage()); + return false; + } + } +} diff --git a/src/Commands/QueueRunCommand.php b/src/Commands/QueueRunCommand.php index 7ada465..14bfcc5 100644 --- a/src/Commands/QueueRunCommand.php +++ b/src/Commands/QueueRunCommand.php @@ -56,10 +56,10 @@ public function __construct(QueueManager $manager) protected function handle(): int { return $this->withTiming(function () { - $queue = $this->getOption('queue', 'default'); - $sleep = (int) $this->getOption('sleep', 3); - $maxMemory = (int) $this->getOption('memory', 128); - $maxTime = (int) $this->getOption('timeout', 3600); + $queue = $this->option('queue', 'default'); + $sleep = (int) $this->option('sleep', 3); + $maxMemory = (int) $this->option('memory', 128); + $maxTime = (int) $this->option('timeout', 3600); $this->info("Starting queue worker on queue: {$queue}"); $this->info("Configuration: sleep={$sleep}s, memory={$maxMemory}MB, timeout={$maxTime}s"); @@ -79,29 +79,4 @@ protected function handle(): int } }, 'Queue worker stopped gracefully.'); } - - /** - * Get an option value. - * - * @param string $key - * @param mixed $default - * @return mixed - */ - protected function getOption(string $key, $default = null) - { - // Implementation depends on your console command system - // This is a placeholder - adapt to your actual implementation - global $argv; - - foreach ($argv as $i => $arg) { - if (strpos($arg, "--{$key}=") === 0) { - return substr($arg, strlen("--{$key}=")); - } - if ($arg === "--{$key}" && isset($argv[$i + 1])) { - return $argv[$i + 1]; - } - } - - return $default; - } } diff --git a/src/QueueServiceProvider.php b/src/QueueServiceProvider.php index 86a771e..9676718 100644 --- a/src/QueueServiceProvider.php +++ b/src/QueueServiceProvider.php @@ -5,6 +5,7 @@ use Phaseolies\Providers\ServiceProvider; use Doppar\Queue\QueueManager; use Doppar\Queue\Commands\QueueRunCommand; +use Doppar\Queue\Commands\QueueRetryCommand; class QueueServiceProvider extends ServiceProvider { @@ -32,7 +33,8 @@ public function boot(): void ], 'migrations'); $this->commands([ - QueueRunCommand::class + QueueRunCommand::class, + QueueRetryCommand::class ]); } }