feature/status-update-optimization #3

Merged
master merged 3 commits from feature/status-update-optimization into main 2025-10-26 12:51:55 +01:00
2 changed files with 48 additions and 19 deletions
Showing only changes of commit ccadbe3b83 - Show all commits

View File

@@ -49,6 +49,9 @@ func (nd *NodeDiscovery) Shutdown(ctx context.Context) error {
return nil return nil
} }
// MessageHandler processes a specific UDP message type
type MessageHandler func(payload string, remoteAddr *net.UDPAddr)
// handleUDPMessage processes incoming UDP messages // handleUDPMessage processes incoming UDP messages
func (nd *NodeDiscovery) handleUDPMessage(message string, remoteAddr *net.UDPAddr) { func (nd *NodeDiscovery) handleUDPMessage(message string, remoteAddr *net.UDPAddr) {
nd.logger.WithFields(log.Fields{ nd.logger.WithFields(log.Fields{
@@ -58,13 +61,39 @@ func (nd *NodeDiscovery) handleUDPMessage(message string, remoteAddr *net.UDPAdd
message = strings.TrimSpace(message) message = strings.TrimSpace(message)
if strings.HasPrefix(message, "CLUSTER_HEARTBEAT:") { // Extract topic by splitting on first ":"
hostname := strings.TrimPrefix(message, "CLUSTER_HEARTBEAT:") parts := strings.SplitN(message, ":", 2)
nd.updateNodeFromHeartbeat(remoteAddr.IP.String(), remoteAddr.Port, hostname) if len(parts) < 2 {
} else if strings.HasPrefix(message, "NODE_UPDATE:") { nd.logger.WithField("message", message).Debug("Invalid message format - missing ':' separator")
nd.handleNodeUpdate(remoteAddr.IP.String(), message) return
} else if !strings.HasPrefix(message, "RAW:") { }
nd.logger.WithField("message", message).Debug("Received unknown UDP message")
topic := parts[0]
payload := parts[1]
// Handler map for different message types
handlers := map[string]MessageHandler{
"cluster/heartbeat": func(payload string, remoteAddr *net.UDPAddr) {
nd.updateNodeFromHeartbeat(remoteAddr.IP.String(), remoteAddr.Port, payload)
},
"node/update": func(payload string, remoteAddr *net.UDPAddr) {
// Reconstruct full message for handleNodeUpdate which expects "node/update:hostname:{json}"
fullMessage := "node/update:" + payload
nd.handleNodeUpdate(remoteAddr.IP.String(), fullMessage)
},
"raw": func(payload string, remoteAddr *net.UDPAddr) {
nd.logger.WithField("message", "raw:"+payload).Debug("Received raw message")
},
"cluster/event": func(payload string, remoteAddr *net.UDPAddr) {
nd.logger.WithField("message", "cluster/event:"+payload).Debug("Received cluster/event message")
},
}
// Look up and execute handler
if handler, exists := handlers[topic]; exists {
handler(payload, remoteAddr)
} else {
nd.logger.WithField("topic", topic).Debug("Received unknown UDP message type")
} }
} }
@@ -138,9 +167,9 @@ func (nd *NodeDiscovery) updateNodeFromHeartbeat(sourceIP string, sourcePort int
} }
} }
// handleNodeUpdate processes NODE_UPDATE messages // handleNodeUpdate processes NODE_UPDATE and node/update messages
func (nd *NodeDiscovery) handleNodeUpdate(sourceIP, message string) { func (nd *NodeDiscovery) handleNodeUpdate(sourceIP, message string) {
// Message format: "NODE_UPDATE:hostname:{json}" // Message format: "NODE_UPDATE:hostname:{json}" or "node/update:hostname:{json}"
parts := strings.SplitN(message, ":", 3) parts := strings.SplitN(message, ":", 3)
if len(parts) < 3 { if len(parts) < 3 {
nd.logger.WithField("message", message).Warn("Invalid NODE_UPDATE message format") nd.logger.WithField("message", message).Warn("Invalid NODE_UPDATE message format")

View File

@@ -134,13 +134,13 @@ func (wss *WebSocketServer) sendCurrentClusterState(conn *websocket.Conn) {
} }
message := struct { message := struct {
Type string `json:"type"` Topic string `json:"topic"`
Members []client.ClusterMember `json:"members"` Members []client.ClusterMember `json:"members"`
PrimaryNode string `json:"primaryNode"` PrimaryNode string `json:"primaryNode"`
TotalNodes int `json:"totalNodes"` TotalNodes int `json:"totalNodes"`
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
}{ }{
Type: "cluster_update", Topic: "cluster/update",
Members: clusterData, Members: clusterData,
PrimaryNode: wss.nodeDiscovery.GetPrimaryNode(), PrimaryNode: wss.nodeDiscovery.GetPrimaryNode(),
TotalNodes: len(nodes), TotalNodes: len(nodes),
@@ -227,13 +227,13 @@ func (wss *WebSocketServer) broadcastClusterUpdate() {
} }
message := struct { message := struct {
Type string `json:"type"` Topic string `json:"topic"`
Members []client.ClusterMember `json:"members"` Members []client.ClusterMember `json:"members"`
PrimaryNode string `json:"primaryNode"` PrimaryNode string `json:"primaryNode"`
TotalNodes int `json:"totalNodes"` TotalNodes int `json:"totalNodes"`
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
}{ }{
Type: "cluster_update", Topic: "cluster/update",
Members: clusterData, Members: clusterData,
PrimaryNode: wss.nodeDiscovery.GetPrimaryNode(), PrimaryNode: wss.nodeDiscovery.GetPrimaryNode(),
TotalNodes: len(wss.nodeDiscovery.GetNodes()), TotalNodes: len(wss.nodeDiscovery.GetNodes()),
@@ -287,12 +287,12 @@ func (wss *WebSocketServer) broadcastNodeDiscovery(nodeIP, action string) {
} }
message := struct { message := struct {
Type string `json:"type"` Topic string `json:"topic"`
Action string `json:"action"` Action string `json:"action"`
NodeIP string `json:"nodeIp"` NodeIP string `json:"nodeIp"`
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
}{ }{
Type: "node_discovery", Topic: "node/discovery",
Action: action, Action: action,
NodeIP: nodeIP, NodeIP: nodeIP,
Timestamp: time.Now().Format(time.RFC3339), Timestamp: time.Now().Format(time.RFC3339),
@@ -330,14 +330,14 @@ func (wss *WebSocketServer) BroadcastFirmwareUploadStatus(nodeIP, status, filena
} }
message := struct { message := struct {
Type string `json:"type"` Topic string `json:"topic"`
NodeIP string `json:"nodeIp"` NodeIP string `json:"nodeIp"`
Status string `json:"status"` Status string `json:"status"`
Filename string `json:"filename"` Filename string `json:"filename"`
FileSize int `json:"fileSize"` FileSize int `json:"fileSize"`
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
}{ }{
Type: "firmware_upload_status", Topic: "firmware/upload/status",
NodeIP: nodeIP, NodeIP: nodeIP,
Status: status, Status: status,
Filename: filename, Filename: filename,
@@ -385,7 +385,7 @@ func (wss *WebSocketServer) BroadcastRolloutProgress(rolloutID, nodeIP, status s
} }
message := struct { message := struct {
Type string `json:"type"` Topic string `json:"topic"`
RolloutID string `json:"rolloutId"` RolloutID string `json:"rolloutId"`
NodeIP string `json:"nodeIp"` NodeIP string `json:"nodeIp"`
Status string `json:"status"` Status string `json:"status"`
@@ -394,7 +394,7 @@ func (wss *WebSocketServer) BroadcastRolloutProgress(rolloutID, nodeIP, status s
Progress int `json:"progress"` Progress int `json:"progress"`
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
}{ }{
Type: "rollout_progress", Topic: "rollout/progress",
RolloutID: rolloutID, RolloutID: rolloutID,
NodeIP: nodeIP, NodeIP: nodeIP,
Status: status, Status: status,