From 827ccbab577c07bd23cc2f2bc73f2f410e3f518a Mon Sep 17 00:00:00 2001 From: MacRimi Date: Tue, 21 Jul 2026 19:25:08 +0200 Subject: [PATCH] update 1.2.4 --- AppImage/components/health-status-modal.tsx | 16 ++++++++-------- AppImage/scripts/flask_health_routes.py | 13 ++++++++++++- CHANGELOG.md | 2 +- web/data/changelog/es.md | 2 +- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/AppImage/components/health-status-modal.tsx b/AppImage/components/health-status-modal.tsx index c03cb6bb..037ced01 100644 --- a/AppImage/components/health-status-modal.tsx +++ b/AppImage/components/health-status-modal.tsx @@ -126,13 +126,13 @@ export function HealthStatusModal({ open, onOpenChange, getApiUrl }: HealthStatu const [expandedCategories, setExpandedCategories] = useState>(new Set()) const [showUpdateTerminal, setShowUpdateTerminal] = useState(false) - const fetchHealthDetails = useCallback(async () => { + const fetchHealthDetails = useCallback(async (force = false) => { setLoading(true) setError(null) try { let newOverallStatus = "OK" - + // Use the new combined endpoint for fewer round-trips const token = getAuthToken() const authHeaders: Record = {} @@ -140,7 +140,7 @@ export function HealthStatusModal({ open, onOpenChange, getApiUrl }: HealthStatu authHeaders["Authorization"] = `Bearer ${token}` } - const response = await fetch(getApiUrl("/api/health/full"), { headers: authHeaders }) + const response = await fetch(getApiUrl(force ? "/api/health/full?refresh=1" : "/api/health/full"), { headers: authHeaders }) let infoCount = 0 if (!response.ok) { @@ -222,7 +222,7 @@ export function HealthStatusModal({ open, onOpenChange, getApiUrl }: HealthStatu if (open) { fetchHealthDetails() // Auto-refresh every 5 minutes while modal is open - const refreshInterval = setInterval(fetchHealthDetails, 300000) + const refreshInterval = setInterval(() => fetchHealthDetails(), 300000) return () => clearInterval(refreshInterval) } }, [open, fetchHealthDetails]) @@ -872,10 +872,10 @@ export function HealthStatusModal({ open, onOpenChange, getApiUrl }: HealthStatu open={showUpdateTerminal} onClose={() => { setShowUpdateTerminal(false) - // Refresh health checks so the "System Updates" row updates - // (pending count / kernel version) without waiting for the - // next polling tick after the update finishes. - fetchHealthDetails().catch(() => {}) + // Force a fresh read (cache-busting via ?refresh=1) so the + // "System Updates" row reflects the state right after the + // update finished, instead of the pre-update cached value. + fetchHealthDetails(true).catch(() => {}) }} scriptPath="/usr/local/share/proxmenux/scripts/utilities/proxmox_update.sh" scriptName="proxmox_update" diff --git a/AppImage/scripts/flask_health_routes.py b/AppImage/scripts/flask_health_routes.py index 0dbe92d0..fb9b0bd7 100644 --- a/AppImage/scripts/flask_health_routes.py +++ b/AppImage/scripts/flask_health_routes.py @@ -230,14 +230,25 @@ def get_full_health(): Get complete health data in a single request: detailed status + active errors + dismissed. Uses background-cached results if fresh (< 6 min) for instant response, otherwise runs a fresh check. + + ?refresh=1 busts the background + per-check caches for updates/services/ + security before returning, so an event that just changed underlying state + (Update Now finished, dismiss action) sees the new value immediately + instead of waiting for the next polling tick. """ import time as _time try: + if request.args.get('refresh') == '1': + for ck in ('updates_check', 'pve_services', 'security_check', + '_bg_detailed', '_bg_overall', 'overall_health'): + health_monitor.last_check_times.pop(ck, None) + health_monitor.cached_results.pop(ck, None) + # Try to use the background-cached detailed result for instant response bg_key = '_bg_detailed' bg_last = health_monitor.last_check_times.get(bg_key, 0) bg_age = _time.time() - bg_last - + if bg_age < 360 and bg_key in health_monitor.cached_results: # Use cached result (at most ~5 min old) details = health_monitor.cached_results[bg_key] diff --git a/CHANGELOG.md b/CHANGELOG.md index 209d10f7..70a54b69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ This release adds two in-dashboard improvements — a one-click Proxmox update t - New **Update Now** button inside the Health Monitor modal, under the **System Updates** section. - Runs the standard Proxmox update flow (`apt update` + `dist-upgrade` + post-update cleanup) in an in-dashboard terminal — no need to open a shell. - Only appears when updates are pending; when the system is up to date the button stays hidden. -- On close, the Health Monitor refreshes so the pending-update count and kernel row update immediately. +- On close, the Health Monitor forces a cache-busting refresh (`/api/health/full?refresh=1`) so the pending-update count and kernel row reflect the post-update state right away, instead of the pre-update value that the background cache had stored moments before the run. - The underlying script is context-aware: on an already-configured production host it respects the operator's custom repositories (never disables enterprise/ceph, never deletes legacy sources, never purges alternate NTP, never force-installs zfsutils/chrony); on a bare host it lays down only the missing base repos. It also detects a newly installed kernel that isn't the running one and prompts for reboot at the end. - During the upgrade, `service_fail` notifications for PVE services (pve-cluster, pveproxy, corosync…) are suppressed — their restart is a normal part of the upgrade cycle. Suppression extends 60 s past apt exit so the trailing restart events don't leak through. diff --git a/web/data/changelog/es.md b/web/data/changelog/es.md index 0185c750..5d03f7c4 100644 --- a/web/data/changelog/es.md +++ b/web/data/changelog/es.md @@ -11,7 +11,7 @@ Esta versión suma dos mejoras visibles en el propio dashboard — un botón par - Nuevo botón **Update Now** dentro del modal del Monitor de Salud, en la sección **System Updates**. - Ejecuta el flujo estándar de actualización de Proxmox (`apt update` + `dist-upgrade` + limpieza posterior) en una terminal dentro del dashboard — sin necesidad de abrir una shell. - Solo aparece cuando hay actualizaciones pendientes; si el sistema está al día, el botón queda oculto. -- Al cerrar, el Monitor de Salud se refresca automáticamente para que el contador de actualizaciones pendientes y la fila del kernel se actualicen al instante. +- Al cerrar, el Monitor de Salud fuerza un refresh con invalidación de caché (`/api/health/full?refresh=1`) para que el contador de actualizaciones pendientes y la fila del kernel reflejen el estado post-actualización al instante, en lugar del valor pre-actualización que la caché de fondo había guardado justo antes de la ejecución. - El script subyacente distingue el contexto: si se ejecuta sobre un host ya en producción, respeta los repositorios personalizados del operador (no desactiva enterprise/ceph, no borra sources legacy, no purga NTP alternativos ni fuerza instalar zfsutils/chrony); si detecta un servidor virgen crea los repos base necesarios. Detecta también si hay un kernel nuevo instalado distinto del que está corriendo y pide el reboot al terminar. - Durante la actualización se suprimen las notificaciones de `service_fail` de servicios PVE (pve-cluster, pveproxy, corosync…) porque su reinicio es parte normal del upgrade; volvían a notificarse hasta 60 s después de que apt termine.