diff --git a/api/main_handler.go b/api/main_handler.go index b01c6ca..848aef0 100644 --- a/api/main_handler.go +++ b/api/main_handler.go @@ -40,6 +40,7 @@ func NewHandler(services APIServices) http.Handler { "allocs", "block", "mutex", + "txpool", "admin", } diff --git a/api/websocket_handler.go b/api/websocket_handler.go index 234c32b..c91f0fd 100644 --- a/api/websocket_handler.go +++ b/api/websocket_handler.go @@ -27,6 +27,7 @@ type WebsocketHandler struct { writeQueue chan []byte conn *websocket.Conn closeChan chan struct{} + closed bool } // **NewWebsocketHandler initializes WebsocketHandler** @@ -35,6 +36,7 @@ func NewWebsocketHandler(conn *websocket.Conn) *WebsocketHandler { writeQueue: make(chan []byte, 100), conn: conn, closeChan: make(chan struct{}), + closed: false, } go handler.startWriter() // Start dedicated writer goroutine @@ -79,6 +81,14 @@ func (h *WebsocketHandler) startWriter() { // **Close WebSocket connection and stop writer** func (h *WebsocketHandler) closeConnection() { + h.mu.Lock() + if h.closed { + h.mu.Unlock() + return + } + h.closed = true + h.mu.Unlock() + close(h.closeChan) h.conn.Close() } @@ -111,10 +121,14 @@ func (h *APIHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request) { for { select { case <-r.Context().Done(): + handler.closeConnection() return case <-handler.closeChan: // Graceful shutdown return - case message := <-channel: + case message, ok := <-channel: + if !ok { + return + } handler.sendResponse(&ClientResponse{ Status: "success", Message: string(message), @@ -128,16 +142,20 @@ func (h *APIHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request) { return nil }) - go func() { - ticker := time.NewTicker(10 * time.Second) - defer ticker.Stop() + pingTicker := time.NewTicker(10 * time.Second) + defer pingTicker.Stop() + go func() { for { select { case <-handler.closeChan: return - case <-ticker.C: + case <-pingTicker.C: handler.mu.Lock() + if handler.closed { + handler.mu.Unlock() + return + } err := conn.WriteMessage(websocket.PingMessage, nil) handler.mu.Unlock() @@ -153,6 +171,14 @@ func (h *APIHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request) { for { _, msg, err := conn.ReadMessage() if err != nil { + if websocket.IsCloseError(err, websocket.CloseNormalClosure) { + fmt.Println("Client closed connection") + break + } else if websocket.IsUnexpectedCloseError(err, websocket.CloseNormalClosure) { + fmt.Println("Client closed connection unexpectedly") + break + } + fmt.Println("Error reading message:", err) break } diff --git a/go.mod b/go.mod index 9058464..e711239 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( ) require ( - github.com/erigontech/erigonwatch v0.1.24 + github.com/erigontech/erigonwatch v0.1.25 github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index ef66603..e5b8659 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/erigontech/erigonwatch v0.1.24 h1:o0Smm0IUg8Ak8sfo0BKht/jos8N9ht8wwqXJ13F5H0k= -github.com/erigontech/erigonwatch v0.1.24/go.mod h1:8vQ+VjvLu2gkPs8EwdPrOTAAo++WuLuBi54N7NuAF0I= +github.com/erigontech/erigonwatch v0.1.25 h1:NRCwI6Np4XHVoL/vfPoFH9cphqIAAtWkXArN+is5Cjs= +github.com/erigontech/erigonwatch v0.1.25/go.mod h1:8vQ+VjvLu2gkPs8EwdPrOTAAo++WuLuBi54N7NuAF0I= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=