Start client code like server side

This commit is contained in:
Nicholas Kariniemi 2014-10-12 22:57:00 +03:00
parent 73cf89f9d5
commit 64b1bb05a7
6 changed files with 71 additions and 35 deletions

View file

@ -12,7 +12,7 @@
(defn start
"Starts the current development system."
[]
(alter-var-root #'system system/start system/dev-config))
(alter-var-root #'system system/start system/dev-system))
(defn stop
"Shuts down and destroys the current development system."

View file

@ -38,15 +38,23 @@
(include-js "/js/grub.js")
[:script {:type "text/javascript"} "goog.require(\"grub.core\")"]]))
(def prod-config
(def prod-system
{:index prod-index-page
:db {:name "grub"}
:port 3000})
:db {:name "grub"
:db nil
:conn nil}
:port 3000
:stop-server nil
:states nil})
(def dev-config
(def dev-system
{:index dev-index-page
:db {:name "grub-dev"}
:port 3000})
:db {:name "grub-dev"
:db nil
:conn nil}
:port 3000
:stop-server nil
:states nil})
(defn handle-websocket [handler states]
(fn [{:keys [websocket?] :as request}]
@ -71,14 +79,14 @@
(handle-root index)
(handle-websocket states)))
(defn start [current {:keys [port db] :as config}]
(defn start [current {:keys [port db] :as system}]
(let [to-db (chan)
db (db/connect-and-handle-events to-db (:name db))
states (state/init-server to-db (db/get-current-state (:db db)))
stop-server (httpkit/run-server (make-handler config states) {:port port})]
stop-server (httpkit/run-server (make-handler system states) {:port port})]
(println "Started server on localhost:" port)
(assoc config
:db (merge (:db config) db)
(assoc system
:db (merge (:db system) db)
:stop-server stop-server
:states states)))
@ -121,8 +129,8 @@
(not= (count arguments) 1) (exit 1 (usage summary))
errors (exit 1 (error-msg errors)))
(case (first arguments)
"development" (start (merge dev-config options))
"dev" (start (merge dev-config options))
"production" (start (merge prod-config options))
"prod" (start (merge prod-config options))
"development" (start (merge dev-system options))
"dev" (start (merge dev-system options))
"production" (start (merge prod-system options))
"prod" (start (merge prod-system options))
(exit 1 (usage summary)))))

View file

@ -1,17 +1,38 @@
(ns grub.core
(:require [grub.state :as state]
[grub.websocket :as ws]
[grub.websocket :as websocket]
[grub.view.app :as view]
[cljs.core.async :as a :refer [<! >! chan]])
(:require-macros [grub.macros :refer [log logs]]))
(defn init-app []
(def system
{:pending-msg (atom nil)
:ws (atom nil)
:channels {:local-states (chan)
:remote-states (chan)
:to-remote (chan)
:from-remote (chan)}
:view-state nil})
(defn start [system]
(let [local-states (chan)
remote-states (chan)
to-remote (chan)
from-remote (chan)]
(view/render-app state/empty-state remote-states local-states)
(ws/connect-client! to-remote from-remote)
(state/init-client from-remote to-remote local-states remote-states)))
from-remote (chan)
view-state (view/render-app state/empty-state remote-states local-states)
ws (websocket/connect (:pending-msg system) to-remote from-remote)
agent-states (state/init-client from-remote to-remote local-states remote-states)]
(assoc system
:ws ws
:channels {:local-states local-states
:remote-states remote-states
:to-remote to-remote
:from-remote from-remote}
:view-state view-state
:agent-states agent-states)))
(init-app)
(defn stop [{:keys [channels ws]} system]
(doseq [c (vals channels)] (a/close! c))
(websocket/disconnect ws))
(start system)

View file

@ -40,4 +40,5 @@
(when (= tag :local) (put! >remote new-state)))})
(go (loop [] (when-let [new-state (<! <remote)]
(reset! state new-state)
(recur))))))
(recur))))
state))

View file

@ -8,34 +8,37 @@
[grub.macros :refer [log logs]]))
(def server-url (str "ws://" (.-host (.-location js/document))))
(def pending-msg (atom nil))
(def reader (t/reader :json))
(def writer (t/writer :json))
(defn send-pending-msg [websocket]
(defn send-pending-msg [websocket pending-msg]
(when (and (.isOpen websocket)
(not (nil? @pending-msg)))
(.send websocket (t/write writer @pending-msg))
(reset! pending-msg nil)))
(defn on-connected [websocket event]
(defn on-connected [websocket pending-msg event]
(log "Connected:" event)
(send-pending-msg websocket))
(send-pending-msg websocket pending-msg))
(defn read-msg [msg]
(t/read reader (.-message msg)))
(defn connect-client! [in out]
(let [handler (goog.events.EventHandler.)
websocket (goog.net.WebSocket.)
listen (fn [type fun] (.listen handler websocket type fun false))]
(listen goog.net.WebSocket.EventType.OPENED (partial on-connected websocket))
(defn connect [pending-msg in out]
(let [ws (goog.net.WebSocket.)
handler (goog.events.EventHandler.)
listen (fn [type fun] (.listen handler ws type fun false))]
(listen goog.net.WebSocket.EventType.OPENED (partial on-connected ws pending-msg))
(listen goog.net.WebSocket.EventType.MESSAGE #(a/put! out (read-msg %)))
(listen goog.net.WebSocket.EventType.CLOSED #(log "Closed:" %))
(listen goog.net.WebSocket.EventType.ERROR #(log "Error:" %))
(go (loop []
(when-let [msg (<! in)]
(reset! pending-msg msg)
(send-pending-msg websocket)
(send-pending-msg ws pending-msg)
(recur))))
(.open websocket server-url)))
(.open ws server-url)
ws))
(defn disconnect [ws]
(.close ws))

View file

@ -7,6 +7,8 @@
#+cljs (:require-macros [grub.macros :refer [log logs]]
[cljs.core.async.macros :refer [go]]))
(def empty-state sync/empty-state)
(defmulti handle-event (fn [event]
#+cljs (logs (:type event))
(:type event)))
@ -98,4 +100,5 @@
(a/put! >view new-state))))
(a/pipe <view local-events)
(make-client-agent (a/merge [local-events <remote]) >remote states)
(a/put! >remote message/full-sync-request)))
(a/put! >remote message/full-sync-request)
states))