Skip to content

Commit

Permalink
add a neffos.IsTryingToReconnect to check if an upgrade error came fr…
Browse files Browse the repository at this point in the history
…om a retry - it gets the total number of retries from the browser as well
  • Loading branch information
kataras committed Jun 25, 2019
1 parent 8a6f560 commit 5314c23
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 26 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ try {
console.log(msg.Body);
}
}
}, { headers: { "X-Username": username } });
}, { headers: { "X-Username": username, reconnect: 5000 } });

const nsConn = await conn.connect("default");
nsConn.emit("chat", "Hello from javascript-side client side!");
Expand Down
4 changes: 3 additions & 1 deletion _examples/basic/browser/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ async function runExample() {
}, {
headers: {
'X-Username': username
}
},
// if > 0 then on network failures it tries to reconnect every 5 seconds, defaults to 0 (disabled).
reconnect: 5000
});

conn.connect("default");
Expand Down
2 changes: 1 addition & 1 deletion _examples/basic/browser/bundle.js

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions _examples/basic/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,21 @@ func startServer() {
return neffos.DefaultIDGenerator(w, r)
}

server.OnUpgradeError = func(err error) {
if retries, ok := neffos.IsTryingToReconnect(err); ok {
log.Printf("a client was tried to reconnect %d times\n", retries)
return
}
log.Printf("ERROR: %v", err)
}

server.OnConnect = func(c *neffos.Conn) error {
log.Printf("[%s] connected to the server.", c)

// if returns non-nil error then it refuses the client to connect to the server.
return nil
}

server.OnDisconnect = func(c *neffos.Conn) {
log.Printf("[%s] disconnected from the server.", c)
}
Expand Down
2 changes: 1 addition & 1 deletion _examples/wrap-conns-to-user/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func server(upgrader neffos.Upgrader) {
// c.Close()
c.Namespace(namespace).Disconnect(nil)
}, false)
} else {
} else {
// srv.Do(func(c *neffos.Conn) {
// c.Write(namespace, "chat", text)
// }, false)
Expand Down
58 changes: 36 additions & 22 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,31 @@ func tryParseURLParamsToHeaders(r *http.Request) {
}
}

type errUpgradeOnGetRetry struct {
retriesStr string
}

func (err errUpgradeOnGetRetry) Error() string {
return err.retriesStr
}

// IsTryingToReconnect reports whether the "err" is from a client
// that was trying to reconnect to the websocket server,
// the first output parameter is the number of total reconnection retries,
// including the previous failures and the succeed last one.
func IsTryingToReconnect(err error) (int, bool) {
if err == nil {
return 0, false
}

if u, ok := err.(errUpgradeOnGetRetry); ok {
retries, _ := strconv.Atoi(u.retriesStr)
return retries, ok
}

return 0, false
}

// Upgrade handles the connection, same as `ServeHTTP` but it can accept
// a socket wrapper and it does return the connection or any errors.
func (s *Server) Upgrade(w http.ResponseWriter, r *http.Request, socketWrapper func(Socket) Socket) (*Conn, error) {
Expand All @@ -207,6 +232,17 @@ func (s *Server) Upgrade(w http.ResponseWriter, r *http.Request, socketWrapper f

socket, err := s.upgrader(w, r)
if err != nil {
// Tthis header key should match with that browser-client's `whenResourceOnline` uses.
if v := r.Header.Get("X-Websocket-Reconnect"); v != "" {
// If that header exists and its not empty then it means that it tries to see if the GET resouce is online,
// let's make the error more useful so it can be checked from callers.
//
// Note that this request will fail at the end
// but the caller can ignore logging it an actual error,
// see the `IsTryingToReconnect` package-level function for more.
err = errUpgradeOnGetRetry{v}
}

if s.OnUpgradeError != nil {
s.OnUpgradeError(err)
}
Expand All @@ -222,28 +258,6 @@ func (s *Server) Upgrade(w http.ResponseWriter, r *http.Request, socketWrapper f
c.readTimeout = s.readTimeout
c.writeTimeout = s.writeTimeout
c.server = s
// TODO: find a way to shutdown this goroutine if not broadcast, or select the other way...
// DONE: found, see `waitMessage`.
// go func(c *conn) {
// for {
// // select {
// // case <-c.closeCh:
// // return
// // default:
// s.broadcastMu.Lock()
// s.broadcastCond.Wait()
//
// if s.broadcastMessage.from != c.ID() {
// if !c.write(s.broadcastMessage) && c.IsClosed() {
// s.broadcastMu.Unlock()
// return
// }
// }
//
// s.broadcastMu.Unlock()
// }

// }(c)

go func(c *Conn) {
for s.waitMessage(c) {
Expand Down

0 comments on commit 5314c23

Please sign in to comment.