From c6748eda41cc7bc7a62e53605e5ec59db746d266 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Tue, 21 Apr 2026 21:57:19 +0200 Subject: [PATCH] Serialize all WebSocket writes (#179) --- pkg/client/websocket.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/client/websocket.go b/pkg/client/websocket.go index b1e0efc..e9fe53d 100644 --- a/pkg/client/websocket.go +++ b/pkg/client/websocket.go @@ -20,6 +20,7 @@ type WebSocketClient struct { conn *websocket.Conn handlers *models.WebSocketEventHandlers mu sync.RWMutex + writeMu sync.Mutex // serializes all writes; gorilla/websocket allows one concurrent writer connected bool reconnect bool ctx context.Context @@ -337,8 +338,12 @@ func (ws *WebSocketClient) pingLoop(config *WebSocketConfig) { } // Set write deadline for ping + ws.writeMu.Lock() _ = conn.SetWriteDeadline(time.Now().Add(10 * time.Second)) - if err := conn.WriteMessage(websocket.PingMessage, nil); err != nil { + err := conn.WriteMessage(websocket.PingMessage, nil) + ws.writeMu.Unlock() + + if err != nil { ws.logger.Printf("Failed to send ping: %v", err) return } @@ -515,9 +520,12 @@ func (ws *WebSocketClient) SendMessage(message []byte) error { return fmt.Errorf("not connected") } + ws.writeMu.Lock() _ = conn.SetWriteDeadline(time.Now().Add(10 * time.Second)) + err := conn.WriteMessage(websocket.TextMessage, message) + ws.writeMu.Unlock() - return conn.WriteMessage(websocket.TextMessage, message) + return err } // PairWithAccount sends a request to pair the device with a specific account