Reconnect automatically when disconnected
- only send all server items when connecting initially - on reconnect, send pending events (that couldn't be sent) - rudimentary solution
This commit is contained in:
parent
307c6cfad5
commit
d4753418ca
2 changed files with 45 additions and 34 deletions
|
@ -27,12 +27,21 @@
|
||||||
(println (count @connected-clients) "client(s) still connected")
|
(println (count @connected-clients) "client(s) still connected")
|
||||||
(a/close! client-chan))
|
(a/close! client-chan))
|
||||||
|
|
||||||
|
(defn send-current-grubs-and-recipes-to-client [client-chan]
|
||||||
|
(let [add-grubs-event {:event :add-grub-list
|
||||||
|
:grubs (db/get-current-grubs)}
|
||||||
|
add-recipes-event {:event :add-recipe-list
|
||||||
|
:recipes (db/get-current-recipes)}]
|
||||||
|
(go (>! client-chan add-grubs-event)
|
||||||
|
(>! client-chan add-recipes-event))))
|
||||||
|
|
||||||
(defn add-event-to-incoming-channel [raw-event ws-channel-id]
|
(defn on-receive [raw-event ws-channel-id client-chan]
|
||||||
(let [parsed-event (read-string raw-event)
|
(let [parsed-event (read-string raw-event)
|
||||||
event (assoc parsed-event :ws-channel ws-channel-id)]
|
event (assoc parsed-event :ws-channel ws-channel-id)]
|
||||||
(println "Received event" event)
|
(println "Received event" event)
|
||||||
(go (>! incoming-events event))))
|
(if (= (:event event) :send-all-items)
|
||||||
|
(send-current-grubs-and-recipes-to-client client-chan)
|
||||||
|
(go (>! incoming-events event)))))
|
||||||
|
|
||||||
(defn forward-other-events-to-client [c ws-channel]
|
(defn forward-other-events-to-client [c ws-channel]
|
||||||
(a/go-loop []
|
(a/go-loop []
|
||||||
|
@ -41,25 +50,13 @@
|
||||||
(httpkit/send! ws-channel (str event))
|
(httpkit/send! ws-channel (str event))
|
||||||
(recur))))
|
(recur))))
|
||||||
|
|
||||||
|
|
||||||
(defn send-current-grubs-and-recipes-to-client [client-chan]
|
|
||||||
(let [add-grubs-event {:event :add-grub-list
|
|
||||||
:grubs (db/get-current-grubs)}
|
|
||||||
add-recipes-event {:event :add-recipe-list
|
|
||||||
:recipes (db/get-current-recipes)}]
|
|
||||||
(go (>! client-chan add-grubs-event)
|
|
||||||
(>! client-chan add-recipes-event))))
|
|
||||||
;(a/pipe (db/get-current-grubs-as-events) client-chan false)
|
|
||||||
;(a/pipe (db/get-current-recipes-as-events) client-chan false))
|
|
||||||
|
|
||||||
(defn setup-new-connection [ws-channel]
|
(defn setup-new-connection [ws-channel]
|
||||||
(let [[ws-channel-id client-chan] (add-connected-client! ws-channel)]
|
(let [[ws-channel-id client-chan] (add-connected-client! ws-channel)]
|
||||||
(println "Client connected:" (.toString ws-channel) (str "(" ws-channel-id ")"))
|
(println "Client connected:" (.toString ws-channel) (str "(" ws-channel-id ")"))
|
||||||
(println (count @connected-clients) "client(s) connected")
|
(println (count @connected-clients) "client(s) connected")
|
||||||
(httpkit/on-close ws-channel #(remove-connected-client! % ws-channel ws-channel-id client-chan))
|
(httpkit/on-close ws-channel #(remove-connected-client! % ws-channel ws-channel-id client-chan))
|
||||||
(httpkit/on-receive ws-channel #(add-event-to-incoming-channel % ws-channel-id))
|
(httpkit/on-receive ws-channel #(on-receive % ws-channel-id client-chan))
|
||||||
(forward-other-events-to-client client-chan ws-channel)
|
(forward-other-events-to-client client-chan ws-channel)))
|
||||||
(send-current-grubs-and-recipes-to-client client-chan)))
|
|
||||||
|
|
||||||
(defn websocket-handler [request]
|
(defn websocket-handler [request]
|
||||||
(httpkit/with-channel request ws-channel (setup-new-connection ws-channel)))
|
(httpkit/with-channel request ws-channel (setup-new-connection ws-channel)))
|
||||||
|
|
|
@ -1,31 +1,45 @@
|
||||||
(ns grub.websocket
|
(ns grub.websocket
|
||||||
(:require [cljs.core.async :as a :refer [<! >! chan]]
|
(:require [cljs.core.async :as a :refer [<! >! chan]]
|
||||||
[cljs.reader])
|
[cljs.reader]
|
||||||
|
goog.net.WebSocket
|
||||||
|
goog.events.EventHandler
|
||||||
|
goog.events.EventTarget)
|
||||||
(:require-macros [cljs.core.async.macros :refer [go go-loop]]
|
(:require-macros [cljs.core.async.macros :refer [go go-loop]]
|
||||||
[grub.macros :refer [log logs]]))
|
[grub.macros :refer [log logs]]))
|
||||||
|
|
||||||
(def websocket* (atom nil))
|
(def websocket* (atom nil))
|
||||||
|
(def pending-events (atom []))
|
||||||
|
|
||||||
|
(defn on-connected [event]
|
||||||
|
(log "Connected:" event)
|
||||||
|
(when (> (count @pending-events))
|
||||||
|
(doseq [event @pending-events] (.send @websocket* event))
|
||||||
|
(reset! pending-events [])))
|
||||||
|
|
||||||
(defn send-outgoing-events [ch]
|
(defn send-outgoing-events [ch]
|
||||||
(go-loop []
|
(go-loop []
|
||||||
(let [event (<! ch)]
|
(let [event (<! ch)]
|
||||||
(.send @websocket* event)
|
(if (.isOpen @websocket*)
|
||||||
(recur))))
|
(.send @websocket* event)
|
||||||
|
(swap! pending-events conj event))
|
||||||
|
(recur))))
|
||||||
|
|
||||||
|
(defn on-message-fn [out]
|
||||||
|
(fn [event]
|
||||||
|
(let [grub-event (cljs.reader/read-string (.-message event))]
|
||||||
|
(go (>! out grub-event)))))
|
||||||
|
|
||||||
(defn receive-remote-events []
|
|
||||||
(let [out (chan)]
|
|
||||||
(aset @websocket*
|
|
||||||
"onmessage"
|
|
||||||
(fn [event]
|
|
||||||
(let [grub-event (cljs.reader/read-string (.-data event))]
|
|
||||||
(go (>! out grub-event)))))
|
|
||||||
out))
|
|
||||||
|
|
||||||
(defn get-remote-chan [to-remote]
|
(defn get-remote-chan [to-remote]
|
||||||
(let [server-url (str "ws://" (.-host (.-location js/document)) "/ws")]
|
(let [server-url (str "ws://" (.-host (.-location js/document)) "/ws")
|
||||||
(reset! websocket* (js/WebSocket. server-url))
|
handler (goog.events.EventHandler.)
|
||||||
(aset @websocket* "onopen" (fn [event] (log "Connected:" event)))
|
remote-events (chan)]
|
||||||
(aset @websocket* "onclose" (fn [event] (log "Connection closed:" event)))
|
(reset! websocket* (goog.net.WebSocket.))
|
||||||
(aset @websocket* "onerror" (fn [event] (log "Connection error:" event)))
|
(.listen handler @websocket* goog.net.WebSocket.EventType.OPENED on-connected false)
|
||||||
|
(.listen handler @websocket* goog.net.WebSocket.EventType.MESSAGE (on-message-fn remote-events) false)
|
||||||
|
(.listen handler @websocket* goog.net.WebSocket.EventType.CLOSED #(log "Closed:" %) false)
|
||||||
|
(.listen handler @websocket* goog.net.WebSocket.EventType.ERROR #(log "Error:" %) false)
|
||||||
(send-outgoing-events to-remote)
|
(send-outgoing-events to-remote)
|
||||||
(receive-remote-events)))
|
(go (>! to-remote {:event :send-all-items}))
|
||||||
|
(.open @websocket* server-url)
|
||||||
|
remote-events))
|
||||||
|
|
Loading…
Reference in a new issue