signalr: AutoReconnect currently broken in main branch code

I hope i don’t disturb the dev experience too much, but AutoReconnect does not work properly (48ff89d7)

When connected to any SignalR server everything is ok. As soon as the opposing server “dies”, the client will spam tons of error messages regarding reading from a closed websocket

example error log

ts=2021-11-02T20:36:43.6823154Z class=Client connection=4lO-LmP8pWerjdOek4MeJg hub=main.testHubHandler level=info event="handshake sent" msg="{\"protocol\":\"messagepack\",\"version\":1}\u001e" error="failed to write msg: WebSocket closed: failed to read frame header: read tcp 127.0.0.1:61265->127.0.0.1:5000: wsarecv: An existing connection was forcibly closed by the remote host."
ts=2021-11-02T20:36:43.6824605Z class=Client connection=4lO-LmP8pWerjdOek4MeJg hub=main.testHubHandler level=info event="handshake sent" msg="{\"protocol\":\"messagepack\",\"version\":1}\u001e" error="failed to write msg: WebSocket closed: failed to read frame header: read tcp 127.0.0.1:61265->127.0.0.1:5000: wsarecv: An existing connection was forcibly closed by the remote host."
ts=2021-11-02T20:36:43.6829672Z class=Client connection=4lO-LmP8pWerjdOek4MeJg hub=main.testHubHandler level=info event="handshake sent" msg="{\"protocol\":\"messagepack\",\"version\":1}\u001e" error="failed to write msg: WebSocket closed: failed to read frame header: read tcp 127.0.0.1:61265->127.0.0.1:5000: wsarecv: An existing connection was forcibly closed by the remote host."
ts=2021-11-02T20:36:43.6834886Z class=Client connection=4lO-LmP8pWerjdOek4MeJg hub=main.testHubHandler level=info event="handshake sent" msg="{\"protocol\":\"messagepack\",\"version\":1}\u001e" error="failed to write msg: WebSocket closed: failed to read frame header: read tcp 127.0.0.1:61265->127.0.0.1:5000: wsarecv: An existing connection was forcibly closed by the remote host."
ts=2021-11-02T20:36:43.6834886Z class=Client connection=4lO-LmP8pWerjdOek4MeJg hub=main.testHubHandler level=info event="handshake sent" msg="{\"protocol\":\"messagepack\",\"version\":1}\u001e" error="failed to write msg: WebSocket closed: failed to read frame header: read tcp 127.0.0.1:61265->127.0.0.1:5000: wsarecv: An existing connection was forcibly closed by the remote host."
ts=2021-11-02T20:36:43.6834886Z class=Client connection=4lO-LmP8pWerjdOek4MeJg hub=main.testHubHandler level=info event="handshake sent" msg="{\"protocol\":\"messagepack\",\"version\":1}\u001e" error="failed to write msg: WebSocket closed: failed to read frame header: read tcp 127.0.0.1:61265->127.0.0.1:5000: wsarecv: An existing connection was forcibly closed by the remote host."
... mutiple thousand lines until the client is closed via CTRL+C

client code

package main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"time"

	"github.com/google/uuid"
	"github.com/philippseith/signalr"
)

func main() {
	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
	defer cancel()

	client, err := signalr.NewClient(ctx,
		signalr.TransferFormat("Binary"),
		signalr.EnableDetailedErrors(true),
		signalr.WithReceiver(&testHubHandler{}),
		// signalr.WithConnection(conn),
		signalr.WithAutoReconnect(func() (signalr.Connection, error) {
			return signalr.NewHTTPConnection(ctx, "http://127.0.0.1:5000/hubs/services", signalr.WithHTTPHeaders(func() http.Header {
				return http.Header{
					"Service-Name":  {"one"},
					"Service-Id":    {uuid.New().String()},
					"Authorization": {"ApiKey 123456"},
				}
			}))
		}),
	)

	if err != nil {
		panic(err)
	}
	client.Start()
}

type testHubHandler struct {
	signalr.Receiver
	nmsg int
}

func (r *testHubHandler) Test() {
	fmt.Printf("test\n")
}
func (r *testHubHandler) Time(t time.Time) {
	r.nmsg++
	if r.nmsg%100 == 0 {
		fmt.Printf("From Server: %s\n", t.Format(time.RFC3339))
	}
}

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 22 (14 by maintainers)

Most upvoted comments

I looked into it with wireshark and it looks like expected. For the go client, the two connections seem to be logical, as the websocket library does not get any tcp handle from the negotiation code.

Nailed it down to client.go:187

err = loop.Run(isLoopConnected)
    if err != nil {
    return err
}

setting conn to nil allows for the reconnect to work