Skip to content

Commit

Permalink
Make websocket reconnect automatically on close
Browse files Browse the repository at this point in the history
to avoid having to reload the page.
  • Loading branch information
mk committed Mar 18, 2023
1 parent 471c270 commit ce0b2be
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 9 deletions.
4 changes: 2 additions & 2 deletions .clj-kondo/config.edn
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
:hooks {:macroexpand {multihash.digest/defhash hooks/defhash}}
:config-in-call {clojure.core/defn {:linters {:unused-binding {:level :off}}}
cljs.core/defn {:linters {:unused-binding {:level :off}}}
clojure.core/fn {:linters {:unused-binding {:level :warning}}}
cljs.core/fn {:linters {:unused-binding {:level :warning}}}
clojure.core/fn {:linters {:unused-binding {:level :off}}}
cljs.core/fn {:linters {:unused-binding {:level :off}}}
clojure.core/let {:linters {:unused-binding {:level :warning}}}
cljs.core/let {:linters {:unused-binding {:level :warning}}}
cljs.core/comment {:linters {:unresolved-symbol {:level :off}
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Changes can be:

To see what's going on while waiting for a long-running computation, Clerk will now show an execution status bar on the top. For named cells (defining a var) it will show the name of the var, for anonymous expressions, a preview of the form.

* 🔌 Make websocket reconnect automatically on close to avoid having to reload the page
* 💫 Cache expressions that return `nil` in memory

## 0.13.842 (2023-03-07)
Expand Down
7 changes: 7 additions & 0 deletions src/nextjournal/clerk/render.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@
{:style {:font-size "0.5rem"} :class "left-[35px] md:left-0 mt-[7px] md:mt-1"}
status]])

(defn connection-status [status]
[:div.absolute.text-red-600.dark:text-white.text-xs.font-sans.ml-1.bg-white.dark:bg-red-800.rounded-full.shadow.z-20.font-bold.px-2.border.border-red-400
{:style {:font-size "0.5rem"} :class "left-[35px] md:left-0 mt-[7px] md:mt-1"}
status])

(defn render-notebook [{:as _doc xs :blocks :keys [bundle? css-class sidenotes? toc toc-visibility]}]
(r/with-let [local-storage-key "clerk-navbar"
navbar-width 220
Expand Down Expand Up @@ -590,6 +595,8 @@
[:<>
[inspect-presented @!doc]
[:div.fixed.w-full.z-20.top-0.left-0.w-full
(when-let [status (:nextjournal.clerk.sci-env/connection-status @!doc)]
[connection-status status])
(when-let [status (:status @!doc)]
[exec-status status])]
(when @!error
Expand Down
28 changes: 25 additions & 3 deletions src/nextjournal/clerk/sci_env.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,6 @@
sci.configs.js-interop/namespaces
sci.configs.reagent/namespaces)})

(defn ^:export onmessage [ws-msg]
(render/dispatch (read-string (.-data ws-msg))))

(defn ^:export eval-form [f]
(sci/eval-form (sci.ctx-store/get-ctx) f))

Expand All @@ -162,6 +159,31 @@

(def ^:export mount render/mount)

(defn ^:export onmessage [ws-msg]
(render/dispatch (read-string (.-data ws-msg))))

(defn reconnect-timeout [failed-connection-attempts]
(get [0 0 100 500 5000] failed-connection-attempts 10000))

(defn ^:export connect [ws-url]
(when (::failed-attempts @render/!doc)
(swap! render/!doc assoc ::connection-status "Reconnecting…"))
(let [ws (js/WebSocket. ws-url)]
(set! (.-onmessage ws) onmessage)
(set! (.-onopen ws) (fn [e] (swap! render/!doc dissoc ::connection-status ::failed-attempts)))
(set! (.-onclose ws) (fn [e]
(let [timeout (reconnect-timeout (::failed-attempts @render/!doc 0))]
(swap! render/!doc
(fn [doc]
(-> doc
(assoc ::connection-status (if (pos? timeout)
(str "Disconnected, reconnecting in " timeout "ms…")
"Reconnecting…"))
(update ::failed-attempts (fnil inc 0)))))
(js/setTimeout #(connect ws-url) timeout))))
(set! (.-clerk_ws ^js goog/global) ws)
(set! (.-ws_send ^js goog/global) (fn [msg] (.send ws msg)))))

(sci.ctx-store/reset-ctx! (sci/init initial-sci-opts))

(sci/enable-unrestricted-access!)
Expand Down
5 changes: 1 addition & 4 deletions src/nextjournal/clerk/view.clj
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,7 @@ let state = " (-> state v/->edn escape-closing-script-tag pr-str) ".replaceAll('
viewer.set_state(viewer.read_string(state));
viewer.mount(document.getElementById('clerk'))\n"
(when conn-ws?
"const ws = new WebSocket(document.location.origin.replace(/^http/, 'ws') + '/_ws')
ws.onmessage = viewer.onmessage;
window.ws_send = msg => ws.send(msg)
")]]))
"viewer.connect(document.location.origin.replace(/^http/, 'ws') + '/_ws')")]]))

(defn ->static-app [{:as state :keys [current-path html]}]
(hiccup/html5
Expand Down

0 comments on commit ce0b2be

Please sign in to comment.