diff --git a/app/Jobs/RunHealthChecks.php b/app/Jobs/RunHealthChecks.php index 1276871..dc17e00 100644 --- a/app/Jobs/RunHealthChecks.php +++ b/app/Jobs/RunHealthChecks.php @@ -27,7 +27,10 @@ class RunHealthChecks implements ShouldQueue foreach ($cards as $key => $card) { $ok = false; foreach ($card['sources'] as $src) { - if ($this->check($src)) { $ok = true; break; } + if ($this->check($src)) { + $ok = true; + break; + } } $svcRows[] = ['name' => $key, 'ok' => $ok]; // labels brauchst du im UI } @@ -35,9 +38,12 @@ class RunHealthChecks implements ShouldQueue // Cache::put(CacheVer::k('health:services'), $svcRows, 60); $payload = ['ts' => time(), 'rows' => $svcRows]; + Cache::put(CacheVer::k('health:services'), $payload, 300); + Cache::put('health:services', $svcRows, 300); Setting::set('woltguard.services', $payload); - Cache::forget('health:services'); } + + } /** Wraps a probe; logs and returns fallback on error */ protected function safe(callable $fn, $fallback = null) @@ -72,9 +78,16 @@ class RunHealthChecks implements ShouldQueue protected function queueWorkers(): array { - $r = Process::run("systemctl is-active supervisor"); - $raw = trim($r->output() ?: $r->errorOutput()); - return ['name'=>'queue', 'ok'=>$raw === 'active', 'raw'=>$raw ?: 'unknown']; + $okQueue = $this->probeSystemd('mailwolt-queue.service'); + $okSched = $this->probeSystemd('mailwolt-schedule.service'); + + $ok = $okQueue && $okSched; + $raw = sprintf('queue:%s sched:%s', $okQueue ? 'active' : 'down', $okSched ? 'active' : 'down'); + + return ['name' => 'queue', 'ok' => $ok, 'raw' => $raw]; +// $r = Process::run("systemctl is-active supervisor"); +// $raw = trim($r->output() ?: $r->errorOutput()); +// return ['name'=>'queue', 'ok'=>$raw === 'active', 'raw'=>$raw ?: 'unknown']; } protected function diskUsage(): array diff --git a/app/Livewire/Ui/System/WoltguardCard.php b/app/Livewire/Ui/System/WoltguardCard.php index f66be06..78b6f95 100644 --- a/app/Livewire/Ui/System/WoltguardCard.php +++ b/app/Livewire/Ui/System/WoltguardCard.php @@ -48,32 +48,45 @@ class WoltguardCard extends Component protected function load(): void { - // 1) Primär: versionierter Cache-Key (mit ts/rows) - $data = Cache::get(CacheVer::k('health:services')); + // 1) Versionierter Key holen + $val = Cache::get(\App\Support\CacheVer::k('health:services')); - // 2) Fallback: Settings (DB) wenn Cache leer/fehlend - if (!is_array($data) || empty($data['rows'])) { - $data = \App\Models\Setting::get('woltguard.services', []); + // 2) Falls leer → Legacy-Key (altes Format: direkt die Rows) + if (empty($val)) { + $legacy = Cache::get('health:services', []); + if (!empty($legacy) && is_array($legacy)) { + $val = ['ts' => null, 'rows' => $legacy]; + } } - // 3) Letzter bekannter Zustand als Notanker (kein Flackern) - $rows = $data['rows'] ?? []; - if (empty($rows) && !empty($this->services)) { - $rows = $this->services; + // 3) DB-Fallback (Settings), wenn weiterhin leer + if (empty($val)) { + $val = \App\Models\Setting::get('woltguard.services'); // erwartet ['ts'=>..,'rows'=>[..]] + } + + // 4) Shape normalisieren + $rows = []; + if (is_array($val)) { + // neues Format + if (array_key_exists('rows', $val) && is_array($val['rows'])) { + $rows = $val['rows']; + } + // falls jemand doch wieder nur die Rows speichert + elseif (isset($val[0]) && is_array($val[0]) && array_key_exists('name', $val[0])) { + $rows = $val; + } } - // ---- Mapping in UI-Props ---- $this->services = $rows; $this->totalCount = count($rows); $this->okCount = collect($rows)->where('ok', true)->count(); - $this->downCount = max(0, $this->totalCount - $this->okCount); - $this->guardOk = ($this->totalCount > 0) && ($this->downCount === 0); + $this->downCount = $this->totalCount - $this->okCount; + $this->guardOk = $this->totalCount > 0 && $this->downCount === 0; $this->downServices = collect($rows) - ->filter(fn ($s) => !($s['ok'] ?? false)) - ->map(fn ($s) => (string)($s['name'] ?? 'unbekannt')) - ->values() - ->all(); + ->filter(fn($s) => !($s['ok'] ?? false)) + ->map(fn($s) => (string)($s['name'] ?? 'unbekannt')) + ->values()->all(); // Badge if ($this->totalCount === 0) { @@ -88,19 +101,68 @@ class WoltguardCard extends Component $this->badgeIcon = 'ph ph-check-circle'; $this->badgeClass = 'text-emerald-300 border-emerald-400/30 bg-emerald-500/10'; } else { - if ($this->downCount >= 3) { - $this->badgeText = "{$this->downCount} Dienste down"; - $this->badgeIcon = 'ph ph-x-circle'; - $this->badgeClass = 'text-rose-300 border-rose-400/30 bg-rose-500/10'; - } else { - $this->badgeText = 'Störung erkannt'; - $this->badgeIcon = 'ph ph-warning-circle'; - $this->badgeClass = 'text-amber-300 border-amber-400/30 bg-amber-500/10'; - } + $this->badgeText = $this->downCount >= 3 ? "{$this->downCount} Dienste down" : 'Störung erkannt'; + $this->badgeIcon = $this->downCount >= 3 ? 'ph ph-x-circle' : 'ph ph-warning-circle'; + $this->badgeClass = $this->downCount >= 3 + ? 'text-rose-300 border-rose-400/30 bg-rose-500/10' + : 'text-amber-300 border-amber-400/30 bg-amber-500/10'; } } // protected function load(): void // { +// // 1) Primär: versionierter Cache-Key (mit ts/rows) +// $data = Cache::get(CacheVer::k('health:services')); +// +// // 2) Fallback: Settings (DB) wenn Cache leer/fehlend +// if (!is_array($data) || empty($data['rows'])) { +// $data = \App\Models\Setting::get('woltguard.services', []); +// } +// +// // 3) Letzter bekannter Zustand als Notanker (kein Flackern) +// $rows = $data['rows'] ?? []; +// if (empty($rows) && !empty($this->services)) { +// $rows = $this->services; +// } +// +// // ---- Mapping in UI-Props ---- +// $this->services = $rows; +// $this->totalCount = count($rows); +// $this->okCount = collect($rows)->where('ok', true)->count(); +// $this->downCount = max(0, $this->totalCount - $this->okCount); +// $this->guardOk = ($this->totalCount > 0) && ($this->downCount === 0); +// +// $this->downServices = collect($rows) +// ->filter(fn ($s) => !($s['ok'] ?? false)) +// ->map(fn ($s) => (string)($s['name'] ?? 'unbekannt')) +// ->values() +// ->all(); +// +// // Badge +// if ($this->totalCount === 0) { +// $this->badgeText = 'keine Daten'; +// $this->badgeIcon = 'ph ph-warning-circle'; +// $this->badgeClass = 'text-amber-300 border-amber-400/30 bg-amber-500/10'; +// return; +// } +// +// if ($this->guardOk) { +// $this->badgeText = 'alle Dienste OK'; +// $this->badgeIcon = 'ph ph-check-circle'; +// $this->badgeClass = 'text-emerald-300 border-emerald-400/30 bg-emerald-500/10'; +// } else { +// if ($this->downCount >= 3) { +// $this->badgeText = "{$this->downCount} Dienste down"; +// $this->badgeIcon = 'ph ph-x-circle'; +// $this->badgeClass = 'text-rose-300 border-rose-400/30 bg-rose-500/10'; +// } else { +// $this->badgeText = 'Störung erkannt'; +// $this->badgeIcon = 'ph ph-warning-circle'; +// $this->badgeClass = 'text-amber-300 border-amber-400/30 bg-amber-500/10'; +// } +// } +// } +// protected function load(): void +// { // // 1) Primär: Redis // $data = Cache::get(CacheVer::k('health:services')); //