diff --git a/extensions/Servers/Proxmox/Livewire/Component.php b/extensions/Servers/Proxmox/Livewire/Component.php index ae78da73e..20b2ae83e 100644 --- a/extensions/Servers/Proxmox/Livewire/Component.php +++ b/extensions/Servers/Proxmox/Livewire/Component.php @@ -4,7 +4,6 @@ namespace Paymenter\Extensions\Servers\Proxmox\Livewire; use App\Helpers\ExtensionHelper; use App\Livewire\Component as BaseComponent; -use Illuminate\Support\Facades\Cache; use Paymenter\Extensions\Servers\Proxmox\Models\Server; use Paymenter\Extensions\Servers\Proxmox\Proxmox; @@ -73,7 +72,7 @@ class Component extends BaseComponent } catch (\Throwable $e) { $this->notify('Action failed: ' . $e->getMessage(), 'error'); } finally { - $this->forceLoadVmStatus(); + $this->loadVmStatus(); } } @@ -247,27 +246,20 @@ class Component extends BaseComponent /** * Refresh the cached VM status from Proxmox. - * Cached for 5 seconds to reduce redundant API calls from polling. */ public function loadVmStatus(): void { - $cacheKey = 'proxmox-vm-status-' . $this->server->id; - try { - $data = Cache::remember($cacheKey, 5, function () { - $proxmox = new Proxmox; - $response = $proxmox->request( - '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/status/current' - ); - - return $response->json()['data'] ?? null; - }); - + $proxmox = new Proxmox; + $response = $proxmox->request( + '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/status/current' + ); + + $data = $response->json()['data'] ?? null; $this->status = $data ? (object) $data : null; } catch (\Illuminate\Http\Client\ConnectionException $e) { // Timeout or connection error - don't log as error, just set status to null \Log::info('Connection timeout loading VM status for server ' . $this->server->id); - Cache::forget($cacheKey); $this->status = null; } catch (\Throwable $e) { \Log::error('Exception loading VM status for server ' . $this->server->id, [ @@ -276,18 +268,7 @@ class Component extends BaseComponent 'node' => $this->server->node->name ?? 'unknown', 'error' => $e->getMessage(), ]); - Cache::forget($cacheKey); $this->status = null; } } - - /** - * Force-refresh VM status by busting the cache. - * Called after lifecycle actions (start/stop) for immediate feedback. - */ - public function forceLoadVmStatus(): void - { - Cache::forget('proxmox-vm-status-' . $this->server->id); - $this->loadVmStatus(); - } } diff --git a/extensions/Servers/Proxmox/Livewire/Server.php b/extensions/Servers/Proxmox/Livewire/Server.php index 876877034..aacf7338c 100644 --- a/extensions/Servers/Proxmox/Livewire/Server.php +++ b/extensions/Servers/Proxmox/Livewire/Server.php @@ -57,46 +57,48 @@ class Server extends Component // Cache for 15 minutes to avoid recalculating for every server return Cache::remember('bandwidth_threshold_95_' . Carbon::now()->format('Y-m'), 900, function () { $startOfMonth = Carbon::now()->startOfMonth(); - - // Use 2 aggregate queries instead of N+1 (was 2*N+1 queries) - $firstStats = ServerStatistics::selectRaw('server_id, MIN(netin) as first_netin, MIN(netout) as first_netout') - ->where('DateTime', '>=', $startOfMonth) - ->groupBy('server_id') - ->pluck(null, 'server_id'); - - $latestStats = ServerStatistics::selectRaw('server_id, MAX(netin) as last_netin, MAX(netout) as last_netout') - ->where('DateTime', '>=', $startOfMonth) - ->groupBy('server_id') - ->pluck(null, 'server_id'); - - if ($firstStats->isEmpty()) { + + // Get all servers + $allServers = ServerModel::all(); + + if ($allServers->isEmpty()) { return 10; // Minimum threshold of 10 GiB } - + $trafficValues = []; - - foreach ($firstStats as $serverId => $first) { - $latest = $latestStats->get($serverId); - if (!$latest) { - continue; + + foreach ($allServers as $server) { + // Get the earliest and latest statistics for this month for each server + $firstStat = ServerStatistics::where('server_id', $server->id) + ->where('DateTime', '>=', $startOfMonth) + ->orderBy('DateTime', 'asc') + ->first(); + + $latestStat = ServerStatistics::where('server_id', $server->id) + ->where('DateTime', '>=', $startOfMonth) + ->orderBy('DateTime', 'desc') + ->first(); + + if ($firstStat && $latestStat) { + // Calculate total traffic (in + out) for the month + $netinDiff = max(0, $latestStat->netin - $firstStat->netin); + $netoutDiff = max(0, $latestStat->netout - $firstStat->netout); + $totalBytes = $netinDiff + $netoutDiff; + + // Convert to GiB and collect + $trafficValues[] = $totalBytes / (1024 * 1024 * 1024); } - - $netinDiff = max(0, $latest->last_netin - $first->first_netin); - $netoutDiff = max(0, $latest->last_netout - $first->first_netout); - $totalBytes = $netinDiff + $netoutDiff; - - $trafficValues[] = $totalBytes / (1024 * 1024 * 1024); } - + if (empty($trafficValues)) { return 10; // Minimum threshold of 10 GiB } - + // Calculate actual 95th percentile by sorting and taking the value at the 95th rank sort($trafficValues); $index = (int) ceil(0.95 * count($trafficValues)) - 1; $threshold95Percent = $trafficValues[$index]; - + // Return the maximum of 95th percentile or 10 GiB minimum return round(max($threshold95Percent, 10), 2); }); diff --git a/extensions/Servers/Proxmox/views/backups.blade.php b/extensions/Servers/Proxmox/views/backups.blade.php index fe8da858c..78d3d0571 100644 --- a/extensions/Servers/Proxmox/views/backups.blade.php +++ b/extensions/Servers/Proxmox/views/backups.blade.php @@ -1,4 +1,4 @@ - +
diff --git a/extensions/Servers/Proxmox/views/backups/create.blade.php b/extensions/Servers/Proxmox/views/backups/create.blade.php index 832733a39..381ede8b6 100644 --- a/extensions/Servers/Proxmox/views/backups/create.blade.php +++ b/extensions/Servers/Proxmox/views/backups/create.blade.php @@ -1,4 +1,4 @@ -
+
+
Overview diff --git a/extensions/Servers/Proxmox/views/cloud-init.blade.php b/extensions/Servers/Proxmox/views/cloud-init.blade.php index 03fe78813..f7e944af8 100644 --- a/extensions/Servers/Proxmox/views/cloud-init.blade.php +++ b/extensions/Servers/Proxmox/views/cloud-init.blade.php @@ -1,4 +1,4 @@ - +