From 9766f6cc7fb7b5c660fdf4b8fc9202af1a06008d Mon Sep 17 00:00:00 2001 From: pounceandmiss Date: Sun, 24 May 2026 07:00:52 -0700 Subject: [PATCH] Resilient session storage: recover on failed startup --- xmpp/component.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/xmpp/component.go b/xmpp/component.go index 1f0ce06..6799a13 100644 --- a/xmpp/component.go +++ b/xmpp/component.go @@ -5,6 +5,7 @@ import ( "regexp" "strconv" "sync" + "sync/atomic" "time" "dev.narayana.im/narayana/telegabber/badger" @@ -21,6 +22,10 @@ import ( var tgConf config.TelegramConfig var sessions map[string]*telegram.Client var db *persistence.SessionsYamlDB + +// componentEverConnected gates SaveSessions in Close(): a shutdown that +// never connected must not overwrite persisted YAML with an empty map. +var componentEverConnected atomic.Bool var sessionLock sync.Mutex const ( @@ -97,6 +102,7 @@ func NewComponent(conf config.XMPPConfig, tc config.TelegramConfig, idsPath stri } sm := xmpp.NewStreamManager(component, func(s xmpp.Sender) { + componentEverConnected.Store(true) go heartbeat(component) }) @@ -247,7 +253,9 @@ func SaveSessions() { }, persistence.SessionMarshaller) } -// Close gracefully terminates the component and saves active sessions +// Close gracefully terminates the component and saves active sessions. +// If the component never reached steady state, SaveSessions is skipped +// to avoid overwriting persisted state with the empty-at-startup map. func Close(component *xmpp.Component) { log.Error("Disconnecting...") @@ -258,8 +266,11 @@ func Close(component *xmpp.Component) { } sessionLock.Unlock() - // save sessions - SaveSessions() + if componentEverConnected.Load() { + SaveSessions() + } else { + log.Warn("Close: component never connected, skipping SaveSessions to preserve on-disk state") + } // flush the ids database gateway.IdsDB.Close()