option('connection') ?: config('queue.default'); $window = max(1, (int) $this->option('window')); $snapshot = QueueHealthService::inspect($connection, $window); $thresholds = QueueHealthService::thresholds(); foreach (['max-age' => 'max_age_minutes', 'max-depth' => 'max_depth', 'max-failed' => 'max_failed'] as $opt => $key) { $val = $this->option($opt); if ($val !== null) { $thresholds[$key] = (int) $val; } } $result = QueueHealthService::evaluate($snapshot, $thresholds); if ($this->option('json')) { $this->line((string) json_encode( ['snapshot' => $snapshot, 'thresholds' => $thresholds] + $result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES )); return $result['ok'] ? self::SUCCESS : self::FAILURE; } $this->line(sprintf('Queue connection: %s (driver: %s)', $snapshot['connection'], $snapshot['driver'] ?? 'unknown')); if ($snapshot['supported']) { if ($snapshot['queues'] === []) { $this->line(' (no jobs queued)'); } else { $rows = []; foreach ($snapshot['queues'] as $name => $q) { $rows[] = [ $name, number_format($q['pending']), number_format($q['due']), number_format($q['delayed']), number_format($q['reserved']), $q['oldest_due_age'] === null ? '—' : intdiv($q['oldest_due_age'], 60).'m', ]; } $this->table(['Queue', 'Pending', 'Due', 'Delayed', 'Reserved', 'Oldest due'], $rows); } } else { $this->warn(sprintf('Per-queue introspection unsupported for the "%s" driver — showing failed jobs only.', $snapshot['driver'] ?? 'unknown')); } $this->line(sprintf( 'Failed jobs: %s total, %s in last %dh', $snapshot['failed_total'] ?? 'n/a', $snapshot['failed_recent'] ?? 'n/a', $snapshot['failed_window_hours'], )); if ($result['ok']) { $this->info('Queue health: OK'); return self::SUCCESS; } $this->newLine(); $this->error('Queue health: '.count($result['breaches']).' issue(s)'); foreach ($result['breaches'] as $b) { $this->line(' • '.$b['message']); } return self::FAILURE; } }