Add send-string, buffer now contains json strs rather than data
Based on commit by vdichev "Replace send-map with send-string with JSON already converted to String", but keeping send-map and moving encoding of buffer before write to keep IE writer consistent with XHRWriter
This commit is contained in:
parent
28f1a7248f
commit
f6d9daf6c5
|
@ -50,9 +50,8 @@
|
|||
(.schedule scheduler f secs TimeUnit/SECONDS))
|
||||
|
||||
;; json responses are sent as "size-of-response\njson-response"
|
||||
(defn size-json-str [data]
|
||||
(let [json (json/json-str data)
|
||||
size (alength (.getBytes json "UTF-8"))]
|
||||
(defn size-json-str [json]
|
||||
(let [size (alength (.getBytes json "UTF-8"))]
|
||||
(str size "\n" json)))
|
||||
|
||||
;; make sure the root URI for channels starts with a / for route matching
|
||||
|
@ -195,7 +194,7 @@
|
|||
(when (seq domain)
|
||||
(async-adapter/write-chunk respond (str "<script>try{document.domain=\"" (pr-str (json/json-str domain)) "\";}catch(e){}</script>\n"))))
|
||||
(write [this data]
|
||||
(async-adapter/write-chunk respond (str "<script>try {parent.m(" (pr-str (json/json-str data)) ")} catch(e) {}</script>\n"))
|
||||
(async-adapter/write-chunk respond (str "<script>try {parent.m(" (pr-str data) ")} catch(e) {}</script>\n"))
|
||||
(when-not write-padding-sent
|
||||
(async-adapter/write-chunk respond ie-stream-padding)
|
||||
(set! write-padding-sent true)))
|
||||
|
@ -225,7 +224,7 @@
|
|||
;; the client acknowledges received arrays when creating a new backwardchannel
|
||||
(acknowledge-arrays [this array-ids])
|
||||
|
||||
(queue-array [this array])
|
||||
(queue-string [this string])
|
||||
|
||||
;; heartbeat is a timer to send noop over the backward channel
|
||||
(clear-heartbeat [this])
|
||||
|
@ -338,7 +337,7 @@
|
|||
(let [session-agent *agent*]
|
||||
(schedule (fn []
|
||||
(send-off session-agent #(-> %
|
||||
(queue-array ["noop"])
|
||||
(queue-string "[\"noop\"]")
|
||||
flush-buffer)))
|
||||
(:heartbeat-interval details))))))
|
||||
(clear-session-timeout [this]
|
||||
|
@ -355,10 +354,10 @@
|
|||
(schedule (fn []
|
||||
(send-off session-agent close "Timed out"))
|
||||
(:session-timeout-interval details))))))
|
||||
(queue-array [this array]
|
||||
(queue-string [this string]
|
||||
(let [next-array-id (inc last-sent-array-id)]
|
||||
(-> this
|
||||
(update-in [:array-buffer] conj [next-array-id array])
|
||||
(update-in [:array-buffer] conj [next-array-id string])
|
||||
(assoc :last-sent-array-id next-array-id))))
|
||||
(acknowledge-arrays [this array-id]
|
||||
(update-in this [:to-confirm-array-ids]
|
||||
|
@ -371,10 +370,15 @@
|
|||
this ;; nothing to do when there's no connection
|
||||
(if-let [buffer (seq array-buffer)]
|
||||
(try
|
||||
;; buffer contains [[1 json-str] ...] can't use
|
||||
;; json-str which will double escape the json
|
||||
(let [data (str "["
|
||||
(str/join "," (map (fn [[n d]] (str "[" n "," d "]")) buffer))
|
||||
"]")]
|
||||
;; write throws exception when the connection is closed
|
||||
(write (:respond back-channel) buffer)
|
||||
(write (:respond back-channel) data))
|
||||
;; size is an approximation
|
||||
(let [this (let [size (reduce + 0 (map count (map json/json-str buffer)))]
|
||||
(let [this (let [size (reduce + 0 (map count (map second buffer)))]
|
||||
(-> this
|
||||
(assoc :array-buffer clojure.lang.PersistentQueue/EMPTY)
|
||||
(assoc :last-sent-array-id (first (last buffer)))
|
||||
|
@ -456,23 +460,24 @@
|
|||
(let [has-back-channel (if (:back-channel session) 1 0)
|
||||
last-sent-array-id (:last-sent-array-id session)
|
||||
;; the sum of all the data that is still to be send
|
||||
;; technically the size is padded by "[","," and "]" dividers inserted by
|
||||
;; the encoding but this number is only used for estimation on
|
||||
;; the client side.
|
||||
outstanding-bytes (let [buffer (:array-buffer session)]
|
||||
(if (empty? buffer)
|
||||
0
|
||||
(reduce + 0 (map count (map json/json-str buffer)))))]
|
||||
(reduce + 0 (map count (map second buffer)))))]
|
||||
[has-back-channel last-sent-array-id outstanding-bytes]))
|
||||
|
||||
;; convience function to send data to a session
|
||||
;; the data will be queued until there is a backchannel to send it over
|
||||
(defn send-map [session-id map]
|
||||
;; the data will be queued until there is a backchannel to send it
|
||||
;; over
|
||||
(defn send-string [session-id string]
|
||||
(when-let [session-agent (get @sessions session-id)]
|
||||
(send-off session-agent #(-> %
|
||||
(queue-array map)
|
||||
(queue-string string)
|
||||
flush-buffer))))
|
||||
|
||||
(defn send-map [session-id map]
|
||||
(send-string session-id (json/json-str map)))
|
||||
|
||||
;; wrap the respond function from :reactor with the proper
|
||||
;; responsewrapper for either IE or other clients
|
||||
(defn wrap-continuation-writers [handler options]
|
||||
|
@ -545,7 +550,7 @@
|
|||
{:status 200
|
||||
:headers (assoc (:headers options) "Content-Type" "application/javascript")
|
||||
:body
|
||||
(size-json-str [[0,["c", session-id, host-prefix, 8]]])})
|
||||
(size-json-str (json/json-str [[0,["c", session-id, host-prefix, 8]]]))})
|
||||
;; For existing sessions:
|
||||
;; Forward sent data by client to listeners
|
||||
;; reply with
|
||||
|
@ -558,7 +563,7 @@
|
|||
(let [status (session-status @session-agent)]
|
||||
{:status 200
|
||||
:headers (:headers options)
|
||||
:body (size-json-str status)})))))
|
||||
:body (size-json-str (json/json-str status))})))))
|
||||
|
||||
;; GET req server->client is a backwardchannel opened by client
|
||||
(defn handle-backward-channel [req session-agent options]
|
||||
|
|
Reference in a new issue