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")
|
||||
(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)
|
||||
event (assoc parsed-event :ws-channel ws-channel-id)]
|
||||
(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]
|
||||
(a/go-loop []
|
||||
|
@ -41,25 +50,13 @@
|
|||
(httpkit/send! ws-channel (str event))
|
||||
(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]
|
||||
(let [[ws-channel-id client-chan] (add-connected-client! ws-channel)]
|
||||
(println "Client connected:" (.toString ws-channel) (str "(" ws-channel-id ")"))
|
||||
(println (count @connected-clients) "client(s) connected")
|
||||
(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))
|
||||
(forward-other-events-to-client client-chan ws-channel)
|
||||
(send-current-grubs-and-recipes-to-client client-chan)))
|
||||
(httpkit/on-receive ws-channel #(on-receive % ws-channel-id client-chan))
|
||||
(forward-other-events-to-client client-chan ws-channel)))
|
||||
|
||||
(defn websocket-handler [request]
|
||||
(httpkit/with-channel request ws-channel (setup-new-connection ws-channel)))
|
||||
|
|
|
@ -1,31 +1,45 @@
|
|||
(ns grub.websocket
|
||||
(: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]]
|
||||
[grub.macros :refer [log logs]]))
|
||||
|
||||
(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]
|
||||
(go-loop []
|
||||
(let [event (<! ch)]
|
||||
(.send @websocket* event)
|
||||
(recur))))
|
||||
(let [event (<! ch)]
|
||||
(if (.isOpen @websocket*)
|
||||
(.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]
|
||||
(let [server-url (str "ws://" (.-host (.-location js/document)) "/ws")]
|
||||
(reset! websocket* (js/WebSocket. server-url))
|
||||
(aset @websocket* "onopen" (fn [event] (log "Connected:" event)))
|
||||
(aset @websocket* "onclose" (fn [event] (log "Connection closed:" event)))
|
||||
(aset @websocket* "onerror" (fn [event] (log "Connection error:" event)))
|
||||
(let [server-url (str "ws://" (.-host (.-location js/document)) "/ws")
|
||||
handler (goog.events.EventHandler.)
|
||||
remote-events (chan)]
|
||||
(reset! websocket* (goog.net.WebSocket.))
|
||||
(.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)
|
||||
(receive-remote-events)))
|
||||
(go (>! to-remote {:event :send-all-items}))
|
||||
(.open @websocket* server-url)
|
||||
remote-events))
|
||||
|
|
Loading…
Reference in a new issue