From 81def7666b96045024a7161393328d612605060b Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Fri, 24 Feb 2023 10:23:31 +0100 Subject: [PATCH] [fix] [#259] Improve client-side detection of broken connections BEFORE THIS COMMIT Client sends regular ping to server on inactivity. When the connection is broken, this sometimes (but not always) triggers a connection close that will then trigger reconnect. AFTER THIS COMMIT Client sends regular ping to server on inactivity AND EXPECTS REPLY FROM SERVER. If the server doesn't reply within a timeout, explicitly triggers a connection close that will then trigger reconnect. --- src/taoensso/sente.cljc | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/taoensso/sente.cljc b/src/taoensso/sente.cljc index a915b90..6ef33d4 100644 --- a/src/taoensso/sente.cljc +++ b/src/taoensso/sente.cljc @@ -775,9 +775,12 @@ ;; No conn send/recv activity w/in kalive window ;; so send ping to client. Should trigger close ;; if conn is broken. - (interfaces/sch-send! server-ch websocket? - (pack packer :chsk/ws-ping))) - (recur udt-t1)))))) + ;; + ;; Might be nice to expect pong reply? Ref. #423 + (interfaces/sch-send! server-ch websocket? + (pack packer :chsk/ws-ping))) + + (recur udt-t1)))))) ;; Ajax handshake/poll (let [_ (tracef "New Ajax handshake/poll: %s (%s)" uid sch-uuid) @@ -805,13 +808,23 @@ (assert websocket?) (upd-conn! :ws uid client-id) (let [[clj ?cb-uuid] (unpack packer req-ppstr)] - (receive-event-msg! clj ; Should be ev - (when ?cb-uuid - (fn reply-fn [resp-clj] ; Any clj form - (tracef "Chsk send (ws reply): %s" resp-clj) - ;; true iff apparent success: + ;; clj should be ev + (if (= clj [:chsk/ws-ping]) + (do + ;; Auto reply to ping + (when-let [cb-uuid ?cb-uuid] (interfaces/sch-send! server-ch websocket? - (pack packer resp-clj ?cb-uuid))))))) + (pack packer "pong" cb-uuid))) + + (receive-event-msg! clj nil)) + + (receive-event-msg! clj + (when ?cb-uuid + (fn reply-fn [resp-clj] ; Any clj form + (tracef "Chsk send (ws reply): %s" resp-clj) + ;; true iff apparent success: + (interfaces/sch-send! server-ch websocket? + (pack packer resp-clj ?cb-uuid)))))))) :on-close ; We rely on `on-close` to trigger for _every_ conn! (fn [server-ch websocket? _status] @@ -1373,7 +1386,14 @@ ;; No conn send/recv activity w/in kalive window ;; so send ping to server. Should trigger close ;; if conn is broken. - (-chsk-send! chsk [:chsk/ws-ping] {:flush? true}))) + (-chsk-send! chsk [:chsk/ws-ping] + {:flush? true + :timeout-ms 5000 ; TODO Configurable + :cb ; Server will auto reply + (fn [reply] + (when (and (have-handle?) (not= reply "pong") #_(= reply :chsk/timeout)) + (-chsk-disconnect! chsk :ws-ping-timeout) + (-chsk-connect! chsk)))}))) (recur))))) chsk)))