From 226bae2b2faa0cd866d4dc7f8cc2e902a3a7a23b Mon Sep 17 00:00:00 2001 From: root Date: Fri, 24 Apr 2026 21:29:57 +0800 Subject: [PATCH] fix: master heartbeat not visible to workers in shared MariaDB mode When master uses SQLite locally, updateNodeState only wrote to local DB. Workers querying shared MariaDB never saw the master's heartbeat. Now master also writes its heartbeat to the shared MariaDB via a temporary connection when MariaDB connection settings are configured. Bump version to v1.6.4. --- config/version | 2 +- web/service/node_sync.go | 31 ++++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/config/version b/config/version index 9d3ffadc..4f1826fe 100644 --- a/config/version +++ b/config/version @@ -1 +1 @@ -v1.6.3 \ No newline at end of file +v1.6.4 \ No newline at end of file diff --git a/web/service/node_sync.go b/web/service/node_sync.go index 5343fa4e..3c8dd95f 100644 --- a/web/service/node_sync.go +++ b/web/service/node_sync.go @@ -40,11 +40,12 @@ func NewNodeSyncService() *NodeSyncService { func (s *NodeSyncService) updateNodeState(version int64, syncErr error, didSync bool) { nodeCfg := config.GetNodeConfigFromJSON() + if nodeCfg.NodeID == "" { + return + } now := time.Now().Unix() state := &model.NodeState{} - if nodeCfg.NodeID != "" { - _ = database.GetDB().First(state, "node_id = ?", nodeCfg.NodeID).Error - } + _ = database.GetDB().First(state, "node_id = ?", nodeCfg.NodeID).Error state.NodeID = nodeCfg.NodeID state.NodeRole = string(nodeCfg.Role) state.LastHeartbeatAt = now @@ -58,6 +59,30 @@ func (s *NodeSyncService) updateNodeState(version int64, syncErr error, didSync state.LastError = "" } _ = database.UpsertNodeState(database.GetDB(), state) + + // Master also writes heartbeat to shared MariaDB so workers can see it + if nodeCfg.Role == config.NodeRoleMaster { + s.writeStateToSharedMariaDB(state) + } +} + +// writeStateToSharedMariaDB opens a temporary connection to the shared +// MariaDB and upserts the given node state. This is needed when the master +// uses SQLite locally but workers query the shared MariaDB for heartbeats. +func (s *NodeSyncService) writeStateToSharedMariaDB(state *model.NodeState) { + dbConfig := config.GetDBConfigFromJSON() + // Only attempt shared write if MariaDB connection settings are configured. + // dbUser is the most reliable indicator — it has no default value. + if dbConfig.User == "" || dbConfig.Host == "" { + return + } + sharedDB, err := database.OpenMariaDB(dbConfig) + if err != nil { + return + } + sqlDB, _ := sharedDB.DB() + defer sqlDB.Close() + _ = database.UpsertNodeState(sharedDB, state) } func (s *NodeSyncService) BootstrapFromCache() error {