From 1cdc01194b03cd62cc427e79c2f6a13190fecb0b Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:18:32 +0200 Subject: [PATCH] feat(proxy-dashboard): implement ProxyDashboardCacheService to manage Traefik dashboard cache; clear cache on configuration changes and proxy actions --- app/Actions/Proxy/SaveConfiguration.php | 4 ++ app/Actions/Proxy/StartProxy.php | 5 ++ app/Actions/Proxy/StopProxy.php | 4 ++ app/Jobs/RestartProxyJob.php | 4 ++ app/Livewire/Server/Navbar.php | 14 ++-- app/Livewire/Server/Proxy.php | 9 +++ app/Services/ProxyDashboardCacheService.php | 67 +++++++++++++++++++ .../execute-container-command.blade.php | 2 +- 8 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 app/Services/ProxyDashboardCacheService.php diff --git a/app/Actions/Proxy/SaveConfiguration.php b/app/Actions/Proxy/SaveConfiguration.php index f2de2b3f5..f0a31aa1b 100644 --- a/app/Actions/Proxy/SaveConfiguration.php +++ b/app/Actions/Proxy/SaveConfiguration.php @@ -3,6 +3,7 @@ namespace App\Actions\Proxy; use App\Models\Server; +use App\Services\ProxyDashboardCacheService; use Lorisleiva\Actions\Concerns\AsAction; class SaveConfiguration @@ -20,6 +21,9 @@ class SaveConfiguration $server->proxy->last_saved_settings = str($docker_compose_yml_base64)->pipe('md5')->value; $server->save(); + // Clear Traefik dashboard cache when configuration is saved + ProxyDashboardCacheService::clearCache($server); + return instant_remote_process([ "mkdir -p $proxy_path", "echo '$docker_compose_yml_base64' | base64 -d | tee $proxy_path/docker-compose.yml > /dev/null", diff --git a/app/Actions/Proxy/StartProxy.php b/app/Actions/Proxy/StartProxy.php index e685adbdf..f98c0d8c2 100644 --- a/app/Actions/Proxy/StartProxy.php +++ b/app/Actions/Proxy/StartProxy.php @@ -5,6 +5,7 @@ namespace App\Actions\Proxy; use App\Enums\ProxyTypes; use App\Events\ProxyStatusChanged; use App\Models\Server; +use App\Services\ProxyDashboardCacheService; use Lorisleiva\Actions\Concerns\AsAction; use Spatie\Activitylog\Models\Activity; @@ -28,6 +29,10 @@ class StartProxy $docker_compose_yml_base64 = base64_encode($configuration); $server->proxy->last_applied_settings = str($docker_compose_yml_base64)->pipe('md5')->value(); $server->save(); + + // Clear Traefik dashboard cache when proxy configuration changes + ProxyDashboardCacheService::clearCache($server); + if ($server->isSwarmManager()) { $commands = $commands->merge([ "mkdir -p $proxy_path/dynamic", diff --git a/app/Actions/Proxy/StopProxy.php b/app/Actions/Proxy/StopProxy.php index 7072c846f..de3ed58a5 100644 --- a/app/Actions/Proxy/StopProxy.php +++ b/app/Actions/Proxy/StopProxy.php @@ -4,6 +4,7 @@ namespace App\Actions\Proxy; use App\Events\ProxyStatusChanged; use App\Models\Server; +use App\Services\ProxyDashboardCacheService; use Lorisleiva\Actions\Concerns\AsAction; class StopProxy @@ -23,6 +24,9 @@ class StopProxy $server->proxy->force_stop = $forceStop; $server->proxy->status = 'exited'; $server->save(); + + // Clear Traefik dashboard cache when proxy stops + ProxyDashboardCacheService::clearCache($server); } catch (\Throwable $e) { return handleError($e); } finally { diff --git a/app/Jobs/RestartProxyJob.php b/app/Jobs/RestartProxyJob.php index 5e862236b..7e867f853 100644 --- a/app/Jobs/RestartProxyJob.php +++ b/app/Jobs/RestartProxyJob.php @@ -6,6 +6,7 @@ use App\Actions\Proxy\CheckProxy; use App\Actions\Proxy\StartProxy; use App\Actions\Proxy\StopProxy; use App\Models\Server; +use App\Services\ProxyDashboardCacheService; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeEncrypted; use Illuminate\Contracts\Queue\ShouldQueue; @@ -39,6 +40,9 @@ class RestartProxyJob implements ShouldBeEncrypted, ShouldQueue StartProxy::run($this->server, force: true); + // Clear Traefik dashboard cache after proxy restart + ProxyDashboardCacheService::clearCache($this->server); + // CheckProxy::run($this->server, true); } catch (\Throwable $e) { return handleError($e); diff --git a/app/Livewire/Server/Navbar.php b/app/Livewire/Server/Navbar.php index 6d4b88d7d..222cca9cd 100644 --- a/app/Livewire/Server/Navbar.php +++ b/app/Livewire/Server/Navbar.php @@ -2,12 +2,12 @@ namespace App\Livewire\Server; -use App\Actions\Proxy\CheckConfiguration; use App\Actions\Proxy\CheckProxy; use App\Actions\Proxy\StartProxy; use App\Actions\Proxy\StopProxy; use App\Jobs\RestartProxyJob; use App\Models\Server; +use App\Services\ProxyDashboardCacheService; use Livewire\Component; class Navbar extends Component @@ -36,17 +36,13 @@ class Navbar extends Component $this->server = $server; $this->currentRoute = request()->route()->getName(); $this->serverIp = $this->server->id === 0 ? base_ip() : $this->server->ip; + $this->loadProxyConfiguration(); } public function loadProxyConfiguration() { try { - $proxy_settings = CheckConfiguration::run($this->server); - if (str($proxy_settings)->contains('--api.dashboard=true') && str($proxy_settings)->contains('--api.insecure=true')) { - $this->traefikDashboardAvailable = true; - } else { - $this->traefikDashboardAvailable = false; - } + $this->traefikDashboardAvailable = ProxyDashboardCacheService::isTraefikDashboardAvailable($this->server); } catch (\Throwable $e) { return handleError($e, $this); } @@ -55,6 +51,8 @@ class Navbar extends Component public function restart() { try { + // Clear cache before restarting proxy + ProxyDashboardCacheService::clearCache($this->server); RestartProxyJob::dispatch($this->server); } catch (\Throwable $e) { return handleError($e, $this); @@ -123,7 +121,7 @@ class Navbar extends Component if ($forceStop) { $this->dispatch('info', 'Proxy is stopped manually.'); } else { - $this->dispatch('info', 'Proxy is stopped manually. Starting in a moment.'); + $this->dispatch('info', 'Proxy is stopped manually.
Starting in a moment.'); } break; default: diff --git a/app/Livewire/Server/Proxy.php b/app/Livewire/Server/Proxy.php index b3dada4ab..d1e414c7b 100644 --- a/app/Livewire/Server/Proxy.php +++ b/app/Livewire/Server/Proxy.php @@ -5,6 +5,7 @@ namespace App\Livewire\Server; use App\Actions\Proxy\CheckConfiguration; use App\Actions\Proxy\SaveConfiguration; use App\Models\Server; +use App\Services\ProxyDashboardCacheService; use Livewire\Component; class Proxy extends Component @@ -41,6 +42,10 @@ class Proxy extends Component { $this->server->proxy = null; $this->server->save(); + + // Clear Traefik dashboard cache when proxy type changes + ProxyDashboardCacheService::clearCache($this->server); + $this->dispatch('reloadWindow'); } @@ -49,6 +54,10 @@ class Proxy extends Component try { $this->server->changeProxy($proxy_type, async: false); $this->selectedProxy = $this->server->proxy->type; + + // Clear Traefik dashboard cache when proxy type is selected + ProxyDashboardCacheService::clearCache($this->server); + $this->dispatch('reloadWindow'); } catch (\Throwable $e) { return handleError($e, $this); diff --git a/app/Services/ProxyDashboardCacheService.php b/app/Services/ProxyDashboardCacheService.php new file mode 100644 index 000000000..2b7aaef62 --- /dev/null +++ b/app/Services/ProxyDashboardCacheService.php @@ -0,0 +1,67 @@ +id}:traefik:dashboard_available"; + } + + /** + * Check if Traefik dashboard is available (from cache or compute) + */ + public static function isTraefikDashboardAvailable(Server $server): bool + { + $cacheKey = static::getCacheKey($server); + + // Try to get from cache first + $cachedValue = Cache::get($cacheKey); + + if ($cachedValue !== null) { + return $cachedValue; + } + + // If not in cache, compute the value + try { + $proxy_settings = \App\Actions\Proxy\CheckConfiguration::run($server); + $dashboardAvailable = str($proxy_settings)->contains('--api.dashboard=true') && + str($proxy_settings)->contains('--api.insecure=true'); + + // Cache the result (cache indefinitely until proxy restart) + Cache::forever($cacheKey, $dashboardAvailable); + + return $dashboardAvailable; + } catch (\Throwable $e) { + // If there's an error checking configuration, default to false and don't cache + return false; + } + } + + /** + * Clear Traefik dashboard cache for a server + */ + public static function clearCache(Server $server): void + { + $cacheKey = static::getCacheKey($server); + Cache::forget($cacheKey); + } + + /** + * Clear Traefik dashboard cache for multiple servers + */ + public static function clearCacheForServers(array $serverIds): void + { + foreach ($serverIds as $serverId) { + $cacheKey = "server:{$serverId}:traefik:dashboard_available"; + Cache::forget($cacheKey); + } + } +} diff --git a/resources/views/livewire/project/shared/execute-container-command.blade.php b/resources/views/livewire/project/shared/execute-container-command.blade.php index f9a0403a6..16b6ac015 100644 --- a/resources/views/livewire/project/shared/execute-container-command.blade.php +++ b/resources/views/livewire/project/shared/execute-container-command.blade.php @@ -17,7 +17,7 @@ @endif -

Terminal

+

Terminal

@if (!$hasShell)