From e110e32320750aa5049a695004574ed9997e829a Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 3 Dec 2025 09:23:57 +0100 Subject: [PATCH 1/3] Fix Traefik warning persistence after proxy restart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When users updated Traefik configuration or version and restarted the proxy, the warning triangle icon showing outdated version info persisted until the weekly CheckTraefikVersionJob ran (Sundays at 00:00). This was caused by the UI warning indicators reading from cached database columns (detected_traefik_version, traefik_outdated_info) that were only updated by the weekly scheduled job, not after proxy restarts. Solution: Add version check to ProxyStatusChangedNotification listener that triggers automatically after proxy status changes to "running". Changes: - Add Traefik version check in ProxyStatusChangedNotification::handle() - Triggers automatically when ProxyStatusChanged event fires with status="running" - Removed duplicate version check from Navbar::restart() (now handled by event) - Event fires after StartProxy/StopProxy actions complete via async jobs - Gracefully handles missing versions.json data with warning log Benefits: - Version check happens AFTER proxy is confirmed running (more accurate) - Reuses existing event infrastructure (ProxyStatusChanged) - Works for all proxy restart scenarios (manual restart, config save + restart, etc.) - No duplicate checks - single source of truth in event listener - Async job runs in background (5-10 seconds) to update database - User sees warning cleared after page refresh Flow: 1. User updates config and restarts proxy (or manually restarts) 2. StartProxy action completes async, dispatches ProxyStatusChanged event 3. ProxyStatusChangedNotification listener receives event 4. Listener checks proxy status = "running", dispatches CheckTraefikVersionForServerJob 5. Job detects version via SSH, updates database columns 6. UI re-renders with cleared warnings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/Listeners/ProxyStatusChangedNotification.php | 16 ++++++++++++++++ app/Livewire/Server/Navbar.php | 16 ---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/Listeners/ProxyStatusChangedNotification.php b/app/Listeners/ProxyStatusChangedNotification.php index 7b23724e2..1d99e7057 100644 --- a/app/Listeners/ProxyStatusChangedNotification.php +++ b/app/Listeners/ProxyStatusChangedNotification.php @@ -2,10 +2,13 @@ namespace App\Listeners; +use App\Enums\ProxyTypes; use App\Events\ProxyStatusChanged; use App\Events\ProxyStatusChangedUI; +use App\Jobs\CheckTraefikVersionForServerJob; use App\Models\Server; use Illuminate\Contracts\Queue\ShouldQueueAfterCommit; +use Illuminate\Support\Facades\Log; class ProxyStatusChangedNotification implements ShouldQueueAfterCommit { @@ -32,6 +35,19 @@ public function handle(ProxyStatusChanged $event) $server->setupDynamicProxyConfiguration(); $server->proxy->force_stop = false; $server->save(); + + // Check Traefik version after proxy is running + if ($server->proxyType() === ProxyTypes::TRAEFIK->value) { + $traefikVersions = get_traefik_versions(); + if ($traefikVersions !== null) { + CheckTraefikVersionForServerJob::dispatch($server, $traefikVersions); + } else { + Log::warning('Traefik version check skipped after proxy status change: versions.json data unavailable', [ + 'server_id' => $server->id, + 'server_name' => $server->name, + ]); + } + } } if ($status === 'created') { instant_remote_process([ diff --git a/app/Livewire/Server/Navbar.php b/app/Livewire/Server/Navbar.php index 6725e5d0a..11effcdc4 100644 --- a/app/Livewire/Server/Navbar.php +++ b/app/Livewire/Server/Navbar.php @@ -5,12 +5,9 @@ use App\Actions\Proxy\CheckProxy; use App\Actions\Proxy\StartProxy; use App\Actions\Proxy\StopProxy; -use App\Enums\ProxyTypes; -use App\Jobs\CheckTraefikVersionForServerJob; use App\Models\Server; use App\Services\ProxyDashboardCacheService; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; -use Illuminate\Support\Facades\Log; use Livewire\Component; class Navbar extends Component @@ -70,19 +67,6 @@ public function restart() $activity = StartProxy::run($this->server, force: true, restarting: true); $this->dispatch('activityMonitor', $activity->id); - - // Check Traefik version after restart to provide immediate feedback - if ($this->server->proxyType() === ProxyTypes::TRAEFIK->value) { - $traefikVersions = get_traefik_versions(); - if ($traefikVersions !== null) { - CheckTraefikVersionForServerJob::dispatch($this->server, $traefikVersions); - } else { - Log::warning('Traefik version check skipped: versions.json data unavailable', [ - 'server_id' => $this->server->id, - 'server_name' => $this->server->name, - ]); - } - } } catch (\Throwable $e) { return handleError($e, $this); } From b1a4853e03b000ba26e92aee2b20542c08cad53b Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 3 Dec 2025 09:53:42 +0100 Subject: [PATCH 2/3] Add missing import for ProxyTypes enum in Navbar component --- app/Livewire/Server/Navbar.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Livewire/Server/Navbar.php b/app/Livewire/Server/Navbar.php index 11effcdc4..d104bce54 100644 --- a/app/Livewire/Server/Navbar.php +++ b/app/Livewire/Server/Navbar.php @@ -5,6 +5,7 @@ use App\Actions\Proxy\CheckProxy; use App\Actions\Proxy\StartProxy; use App\Actions\Proxy\StopProxy; +use App\Enums\ProxyTypes; use App\Models\Server; use App\Services\ProxyDashboardCacheService; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; From 13b7c3dbfc8a33dd7a3399ff923e1b1bd986231e Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 3 Dec 2025 09:56:04 +0100 Subject: [PATCH 3/3] Add real-time UI updates after Traefik version check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dispatch ProxyStatusChangedUI event after version check completes so the UI updates in real-time without requiring page refresh. Changes: - Add ProxyStatusChangedUI::dispatch() at all exit points in CheckTraefikVersionForServerJob - Ensures UI refreshes automatically via WebSocket when version check completes - Works for all scenarios: version detected, using latest tag, outdated version, up-to-date User experience: - User restarts proxy - Warning clears automatically in real-time (no refresh needed) - Leverages existing WebSocket infrastructure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/Jobs/CheckTraefikVersionForServerJob.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/Jobs/CheckTraefikVersionForServerJob.php b/app/Jobs/CheckTraefikVersionForServerJob.php index 88484bcce..92ec4cbd4 100644 --- a/app/Jobs/CheckTraefikVersionForServerJob.php +++ b/app/Jobs/CheckTraefikVersionForServerJob.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use App\Events\ProxyStatusChangedUI; use App\Models\Server; use App\Notifications\Server\TraefikVersionOutdated; use Illuminate\Bus\Queueable; @@ -38,6 +39,8 @@ public function handle(): void $this->server->update(['detected_traefik_version' => $currentVersion]); if (! $currentVersion) { + ProxyStatusChangedUI::dispatch($this->server->team_id); + return; } @@ -48,16 +51,22 @@ public function handle(): void // Handle empty/null response from SSH command if (empty(trim($imageTag))) { + ProxyStatusChangedUI::dispatch($this->server->team_id); + return; } if (str_contains(strtolower(trim($imageTag)), ':latest')) { + ProxyStatusChangedUI::dispatch($this->server->team_id); + return; } // Parse current version to extract major.minor.patch $current = ltrim($currentVersion, 'v'); if (! preg_match('/^(\d+\.\d+)\.(\d+)$/', $current, $matches)) { + ProxyStatusChangedUI::dispatch($this->server->team_id); + return; } @@ -77,6 +86,8 @@ public function handle(): void $this->server->update(['traefik_outdated_info' => null]); } + ProxyStatusChangedUI::dispatch($this->server->team_id); + return; } @@ -96,6 +107,9 @@ public function handle(): void // Fully up to date $this->server->update(['traefik_outdated_info' => null]); } + + // Dispatch UI update event so warning state refreshes in real-time + ProxyStatusChangedUI::dispatch($this->server->team_id); } /**