Closed x0y0z0tn closed 1 year ago
The WebSocket may not be closed after the reconnection.
The only way I found to close the Websocket was to cast the Connection
to WebsocketConnection
ws, ok := currConn.(*signalr.WebSocketConnection)
if ok {
ws.Close()
}
and to do that I added a Close
method to the webSocketConnection
and I changed to uppercase the first letter of the struct name: fromwebsocketConnection
to WebsocketConnection
.
diff --git a/client.go b/client.go
index 0ddb3e4..8b04ac0 100644
--- a/client.go
+++ b/client.go
@@ -270 +270 @@ func (c *client) setupConnectionAndProtocol() (hubProtocol, error) {
- if wsConn, ok := c.conn.(*webSocketConnection); ok {
+ if wsConn, ok := c.conn.(*WebSocketConnection); ok {
diff --git a/websocketconnection.go b/websocketconnection.go
index 4d079e9..3d141d1 100644
--- a/websocketconnection.go
+++ b/websocketconnection.go
@@ -11 +11 @@ import (
-type webSocketConnection struct {
+type WebSocketConnection struct {
@@ -17,2 +17,2 @@ type webSocketConnection struct {
-func newWebSocketConnection(ctx context.Context, connectionID string, conn *websocket.Conn) *webSocketConnection {
- w := &webSocketConnection{
+func newWebSocketConnection(ctx context.Context, connectionID string, conn *websocket.Conn) *WebSocketConnection {
+ w := &WebSocketConnection{
@@ -25 +25,6 @@ func newWebSocketConnection(ctx context.Context, connectionID string, conn *webs
-func (w *webSocketConnection) Write(p []byte) (n int, err error) {
+// Close closes the connection.
+func (w *WebSocketConnection) Close() error {
+ return w.conn.Close(websocket.StatusNormalClosure, "")
+}
+
+func (w *WebSocketConnection) Write(p []byte) (n int, err error) {
@@ -45 +50 @@ func (w *webSocketConnection) Write(p []byte) (n int, err error) {
-func (w *webSocketConnection) Read(p []byte) (n int, err error) {
+func (w *WebSocketConnection) Read(p []byte) (n int, err error) {
@@ -61 +66 @@ func (w *webSocketConnection) Read(p []byte) (n int, err error) {
-func (w *webSocketConnection) TransferMode() TransferMode {
+func (w *WebSocketConnection) TransferMode() TransferMode {
@@ -65 +70 @@ func (w *webSocketConnection) TransferMode() TransferMode {
-func (w *webSocketConnection) SetTransferMode(transferMode TransferMode) {
+func (w *WebSocketConnection) SetTransferMode(transferMode TransferMode) {
I don't know if I am in the correct way.
Your are provoking the reconnect deliberately with creationCtx, _ := context.WithTimeout(context.Background(), 10*time.Second)
, right?
In the end, this context goes into https://github.com/philippseith/signalr/blob/7237db33c21b454ced6c212f290cde3f5aaf87d7/websocketconnection.go#L48 (or into the corresponding Write) and cancels it. The websocket docs at https://pkg.go.dev/nhooyr.io/websocket@v1.8.7#Conn state that any error on any method will close the websocket connection. But this seems not to be the case when the context is canceled. For such cases, the ReadWriteWithContext
wrapper has an unblock
method parameter, which in case of the webSocketConnection
is empty.
https://github.com/philippseith/signalr/blob/7237db33c21b454ced6c212f290cde3f5aaf87d7/websocketconnection.go#L54
Can you try what happens if you pass func() { _ = w.conn.Close(1000, "") }
instead?
thanks for your answer.
Your are provoking the reconnect deliberately with creationCtx, _ := context.WithTimeout(context.Background(), 10*time.Second), right?
No, I am not provoking the reconnect deliberately, sometimes the server disconnects, and the reconnection starts (and don't have control over the server, I'm subscribed to the server with the client).
In the end, this context goes into
I am not sure about that because, when you create a NewHTTPConnection
you use one context (the creation of the connection context)
...
creationCtx, _ := context.WithTimeout(context.Background(), 10*time.Second)
conn, err = signalr.NewHTTPConnection(creationCtx, address)
...
and the WebSocket is created with another context
if I understood the code correctly the connection creation context is not related to this line
Upps, https://github.com/philippseith/signalr/blob/7237db33c21b454ced6c212f290cde3f5aaf87d7/httpconnection.go#L133 might be a bug, I think ctx
should be passed.
But that does not solve the problem.
Because the reconnect is caused by a serverside problem, the websocket documentations statement "any error on any method closes the connection" seems not to be fully true and adding _ = w.conn.Close(1000, err.Error())
after https://github.com/philippseith/signalr/blob/7237db33c21b454ced6c212f290cde3f5aaf87d7/websocketconnection.go#L40 and https://github.com/philippseith/signalr/blob/7237db33c21b454ced6c212f290cde3f5aaf87d7/websocketconnection.go#L56
should be reasonable.
thanks for your answer.
Yes, with your suggestion _ = w.conn.Close(1000, err.Error())
the goroutines don't increase after the reconnection.
Please tell me when you upload the change to apply it and monitor it during the next days.
Thanks again.
I'm going to close the issue. With the change, locally everything looks fine, if during the next days I find anything weird related to it, I'm going to reopen the issue.
Thanks a lot!!
Hi, I am using
WithConnector
to reconnect, after reconnection, I have seen how the goroutines increase.I used with
dlv
to identify which goroutines increased and I have seen how the goroutinewebsocket.(*Conn).timeoutLoop
increased in every reconnection.I am using this code:
Am I reconnecting in the wrong way?
Thanks in advance for your help.