|
20 | 20 | :loop-ping? false |
21 | 21 | :flow nil}) |
22 | 22 |
|
23 | | -(defn clj->transit-str [arg] |
| 23 | +(def default-write-handler (transit/write-handler "default" (fn [obj] (str obj)))) |
| 24 | + |
| 25 | +(defn transit-str-writer [data user-handlers] |
24 | 26 | (let [out (ByteArrayOutputStream. 4096) |
25 | | - writer (transit/writer out :json)] |
26 | | - (transit/write writer arg) |
| 27 | + writer (transit/writer out :json {:handlers user-handlers |
| 28 | + :default-handler default-write-handler})] |
| 29 | + (transit/write writer data) |
27 | 30 | (.toString out))) |
28 | 31 |
|
29 | | -(defn transit-str->clj [arg] |
| 32 | +(defn transit-str-reader [arg] |
30 | 33 | (let [arg-json (json/read-str arg) |
31 | 34 | arg-bytes (.getBytes arg-json "UTF-8") |
32 | 35 | in (ByteArrayInputStream. arg-bytes) |
|
42 | 45 |
|
43 | 46 | (defn send-message [state message] |
44 | 47 | (doall (for [channel (:channels @state)] |
45 | | - (httpkit/send! channel (clj->transit-str message))))) |
| 48 | + (httpkit/send! channel (transit-str-writer message (:handlers @state)))))) |
46 | 49 |
|
47 | 50 | (defn loop-ping [state] |
48 | 51 | (async/thread |
49 | 52 | (loop [s state] |
50 | 53 | (if (:loop-ping? @s) |
51 | | - (do (send-message state {:action :ping :data (reduce-kv |
52 | | - (fn [res k v] |
53 | | - (assoc res k (mainline-chan-meta v))) |
54 | | - {} |
55 | | - (flow/ping (:flow @state)))}) |
| 54 | + (do (send-message state {:action :ping :data (d/datafy (reduce-kv |
| 55 | + (fn [res k v] |
| 56 | + (assoc res k (mainline-chan-meta v))) |
| 57 | + {} |
| 58 | + (flow/ping (:flow @state))))}) |
56 | 59 | (Thread/sleep 1000) |
57 | 60 | (recur s)) |
58 | 61 | (println "Ping loop stopped"))))) |
|
67 | 70 | (swap! state assoc-in [:loop-ping?] true) |
68 | 71 | (loop-ping state)) |
69 | 72 | :on-receive (fn [ch data] |
70 | | - (let [clj-data (transit-str->clj data) |
| 73 | + (let [clj-data (transit-str-reader data) |
71 | 74 | action (:action clj-data)] |
72 | 75 | (case action |
73 | 76 | :inject (flow/inject (:flow @state) (:target clj-data) (edn/read-string (:data clj-data))) |
|
115 | 118 | - opts: A map with the following keys: |
116 | 119 | - :flow (required) - The return value from clojure.core.async.flow/create-flow |
117 | 120 | - :port (optional) - The port to run the server on (default: 9998) |
| 121 | + - :handlers (optional) - A map of custom Transit write handlers to use when serializing state |
| 122 | + data to send to the frontend. These handlers should follow the format |
| 123 | + expected by cognitect.transit/writer :handlers |
118 | 124 |
|
119 | 125 | Returns: |
120 | 126 | An atom containing the server's state, and prints a local url where the frontend can be reached" |
121 | | - [{:keys [flow port] :or {port 9998}}] |
| 127 | + [{:keys [flow port handlers] :or {port 9998}}] |
122 | 128 | (let [state (atom default-state) |
123 | 129 | error-chan (:clojure.datafy/obj (meta (:error (:chans (d/datafy flow))))) |
124 | 130 | report-chan (:clojure.datafy/obj (meta (:report (:chans (d/datafy flow)))))] |
125 | | - (swap! state assoc :flow flow) |
| 131 | + (swap! state assoc :flow flow :handlers handlers) |
126 | 132 | (report-monitoring state report-chan error-chan) |
127 | 133 | (let [server (httpkit/run-server (app state) {:port port |
128 | 134 | :max-body 100000000 |
|
0 commit comments