Fix: Mailbox Stats über Dovecot mit config/mailpool.php

main v1.0.62
boban 2025-10-26 20:03:50 +01:00
parent a5e745ca4a
commit d65aaf9a5d
2 changed files with 105 additions and 30 deletions

View File

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

View File

@ -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'));
//