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 @@