controller: config-apply self-restart + manual restart button (A)
POST /api/config/apply now takes effect via a graceful SELF-RESTART instead of logging "restart needed" and leaving stale in-process singletons (the CF client is built once at startup, so a rotated Cloudflare token never applied until a manual LXC restart). Container is restart:unless-stopped, so a clean os.Exit(0) auto-restarts with fresh config. - New gracefulSelfRestart helper behind an injectable Restarter seam (Router.restart + SetRestarter) so the exit is unit-testable. - configApply: no-op guard (byte-identical re-push → no write, no restart), else write → 200 (flushed) → restart. Removed stale "restart needed" wording. - Removed the dead OnConfigApplied hook (Phase-1-retired infra-backup push; the self-restart reloads everything and a fresh report is pushed on startup). - New POST /api/selfrestart (auth+CSRF via /api/ mount) + "Vezérlő újraindítása" settings button: confirm → POST → poll GET / every 2s → reload. - Tests: changed→restart once; identical→not called (companion); invalid→not called; selfrestart→restart once. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1112,9 +1112,42 @@ window.__registeredPaths=[{{range .StoragePaths}}{{if .Path}}"{{.Path}}",{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section: Controller restart (self-serve) -->
|
||||
<div class="settings-card">
|
||||
<h3>Vezérlő újraindítása</h3>
|
||||
<p class="settings-card-desc">
|
||||
Ha a vezérlő hibásan működik, itt biztonságosan újraindíthatja — nem kell az egész szervert újraindítani.
|
||||
Az alkalmazásai futnak tovább; csak a vezérlő indul újra (néhány másodperc).
|
||||
</p>
|
||||
<div id="restart-status"></div>
|
||||
<button type="button" class="btn btn-outline" id="btn-restart-controller" onclick="restartController()">Vezérlő újraindítása</button>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<script>
|
||||
function restartController() {
|
||||
if (!confirm('Biztosan újraindítja a vezérlőt? A művelet néhány másodpercig tart, és a felület rövid időre elérhetetlen lesz.')) return;
|
||||
var btn = document.getElementById('btn-restart-controller');
|
||||
var status = document.getElementById('restart-status');
|
||||
btn.disabled = true;
|
||||
status.innerHTML = '<div class="alert alert-info">Újraindítás folyamatban… újracsatlakozás…</div>';
|
||||
fetch('/api/selfrestart', { method: 'POST', headers: csrfHeaders() })
|
||||
.then(function(){ pollRestart(0); })
|
||||
.catch(function(){ pollRestart(0); }); // connection may drop as the process exits — poll regardless
|
||||
}
|
||||
function pollRestart(attempt) {
|
||||
if (attempt > 60) { // ~2 min cap — never leave the user on a dead page silently
|
||||
document.getElementById('restart-status').innerHTML =
|
||||
'<div class="alert alert-error">Az újraindítás a vártnál tovább tart. Töltse újra az oldalt kézzel.</div>';
|
||||
return;
|
||||
}
|
||||
setTimeout(function(){
|
||||
fetch('/', { method: 'GET', cache: 'no-store' })
|
||||
.then(function(r){ if (r.ok) { window.location.reload(); } else { pollRestart(attempt + 1); } })
|
||||
.catch(function(){ pollRestart(attempt + 1); });
|
||||
}, 2000);
|
||||
}
|
||||
function editStorageLabel(path, currentLabel) {
|
||||
var wrap = document.getElementById('label-wrap-' + path);
|
||||
if (!wrap) return;
|
||||
|
||||
Reference in New Issue
Block a user