controller v0.67.4: startup recreate also recovers exited/restarting drive-backed apps

recreateBootStaleApps recreates a present drive-backed app when boot-stale OR
exited/restarting/unhealthy (the recency-only gate missed already-exited apps).
Still skips healthy long-running + cleanly user-stopped apps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 17:46:08 +02:00
parent 91a6dcfa75
commit be95a16246
2 changed files with 17 additions and 3 deletions
+10 -3
View File
@@ -10,6 +10,7 @@ import (
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
"gitea.dooplex.hu/admin/felhom-controller/internal/stacks"
)
// Intermediary-mount model (controller side). Post-migration a drive is visible in the guest ONLY at its
@@ -249,10 +250,16 @@ func (s *Server) recreateBootStaleApps() {
if hdd == "" || !strings.HasPrefix(hdd, StableParentDir+"/") || !presentStable[hdd] {
continue
}
if !s.stackStartedRecently(st.Name, 5*time.Minute) {
continue // long-running across a controller-only restart — don't bounce it
// Recreate when the app is boot-stale or not cleanly running: recently-started (it likely came up
// on the empty bind before the drive was re-propagated) OR currently exited/restarting/unhealthy
// (came up wrong and bailed). SKIP a healthy long-running app (no bounce on a controller-only
// restart) and a cleanly user-Stopped app (respect the user's intent).
needs := s.stackStartedRecently(st.Name, 5*time.Minute) ||
st.State == stacks.StateExited || st.State == stacks.StateRestarting || st.State == stacks.StateUnhealthy
if !needs {
continue
}
s.logger.Printf("[INFO] [gate] startup: recreating drive-backed app %s onto its (re-propagated) drive %s", st.Name, hdd)
s.logger.Printf("[INFO] [gate] startup: recreating drive-backed app %s (state=%s) onto its drive %s", st.Name, st.State, hdd)
_ = s.stackMgr.StopStack(st.Name)
if serr := s.stackMgr.StartStack(st.Name); serr != nil {
s.logger.Printf("[WARN] [gate] startup recreate %s: %v", st.Name, serr)