$branches]); // Query all servers with Traefik proxy that are reachable $servers = Server::whereNotNull('proxy') ->whereProxyType(ProxyTypes::TRAEFIK->value) ->whereRelation('settings', 'is_reachable', true) ->whereRelation('settings', 'is_usable', true) ->get(); $serverCount = $servers->count(); Log::info("CheckTraefikVersionJob: Found {$serverCount} server(s) with Traefik proxy"); if ($serverCount === 0) { Log::info('CheckTraefikVersionJob: No Traefik servers found, job completed'); return; } // Dispatch individual server check jobs in parallel Log::info('CheckTraefikVersionJob: Dispatching parallel server check jobs'); foreach ($servers as $server) { CheckTraefikVersionForServerJob::dispatch($server, $traefikVersions); } Log::info("CheckTraefikVersionJob: Dispatched {$serverCount} parallel server check jobs"); // Dispatch notification job with delay to allow server checks to complete // For 1000 servers with 60s timeout each, we need at least 60s delay // But jobs run in parallel via queue workers, so we only need enough time // for the slowest server to complete $delaySeconds = min(300, max(60, (int) ($serverCount / 10))); // 60s minimum, 300s maximum, 0.1s per server NotifyOutdatedTraefikServersJob::dispatch()->delay(now()->addSeconds($delaySeconds)); Log::info("CheckTraefikVersionJob: Scheduled notification job with {$delaySeconds}s delay"); Log::info('CheckTraefikVersionJob: Job completed successfully - parallel processing initiated'); } catch (\Throwable $e) { Log::error('CheckTraefikVersionJob: Error checking Traefik versions: '.$e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), ]); throw $e; } } }