Files
felhom-controller/controller/internal/stacks/life_records.go
T
admin 820e8efde1
gates / gates (push) Successful in 26s
v0.276.0: a restore and a drive move keep the app's records (R-697, R-700)
A drive move persisted through the restore's fresh app.yaml write and dropped the pin: the syncer
then copied the catalog verbatim and the next start jumped the app past its ladder (R-700).
persistDriveFlip now changes HDD_PATH and nothing else. The restore's write carries the life
records (conversion copies, desired_state, update history) from the app.yaml it replaces, and a
second conversion no longer overwrites the first kept copy's record (R-697).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-27 17:59:04 +02:00

42 lines
2.1 KiB
Go

package stacks
import "log"
// carryLifeRecords copies, from the app.yaml a restore is about to replace (prior, as on disk), the records
// that describe the app's LIFE on this box rather than its definition (R-697, v0.276.0). The restore's
// write is a fresh AppConfig by design — the env, the locked fields and the pin come from the unit — and it
// used to drop these with it:
//
// - conversion_copy + earlier_conversion_copies: a kept pre-conversion datadir copy whose record is dropped
// is never released (R-697, measured on 9202). A restore does not remove the volume, so it must not
// forget it either.
// - desired_state: the household's intent. Dropped, a dead app after a restore was read as "unknown
// intent" and never alarmed (R-166's absent case).
// - failed_update_step, last_update_undone, last_auto_update: the ladder's history on THIS box; the
// automatic leg must not re-press a step that already failed here because a restore happened.
//
// NOT carried: pinned_images (the restore pins to the unit's definition right after — carrying the old pin
// would freeze a failed SetPin onto the wrong version), installed_images (an observation of what ran
// before the restore, possibly another version), restored_logins (computed per restore).
// Pinned by TestR697_ARestoreKeepsTheConversionCopyRecordSoTheCopyIsReleased.
func carryLifeRecords(logger *log.Logger, name string, prior, cfg *AppConfig) {
if prior == nil {
return
}
cfg.ConversionCopy = prior.ConversionCopy
cfg.EarlierConversionCopies = prior.EarlierConversionCopies
if cfg.DesiredState == "" {
cfg.DesiredState = prior.DesiredState
}
cfg.FailedStep = prior.FailedStep
cfg.LastUpdateUndone = prior.LastUpdateUndone
cfg.LastAutoUpdate = prior.LastAutoUpdate
if n := len(prior.EarlierConversionCopies); prior.ConversionCopy != nil || n > 0 {
cur := ""
if prior.ConversionCopy != nil {
cur = prior.ConversionCopy.Copy
}
logger.Printf("[INFO] [stacks] %s: the restore keeps the record of the kept pre-conversion copy %q (+%d earlier) — it is released when a backup written by the converted engine is proven", name, cur, n)
}
}