started the rest api
This commit is contained in:
1 parent
516cccf4cd
commit
ad924ca5c7
10 files changed
+320
-91
No files matched your search
@@ -15,19 +15,33 @@
|
|||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="Leiningen: cheshire:5.8.0" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: clj-time:0.14.2" level="project" />
|
<orderEntry type="library" name="Leiningen: clj-time:0.14.2" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: clj-tuple:0.2.2" level="project" />
|
<orderEntry type="library" name="Leiningen: clj-tuple:0.2.2" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: clojure-complete:0.2.4" level="project" />
|
<orderEntry type="library" name="Leiningen: clojure-complete:0.2.4" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: clout:2.2.1" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: colorize:0.1.1" level="project" />
|
<orderEntry type="library" name="Leiningen: colorize:0.1.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.fasterxml.jackson.core/jackson-core:2.9.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.fasterxml.jackson.dataformat/jackson-dataformat-cbor:2.9.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: com.fasterxml.jackson.dataformat/jackson-dataformat-smile:2.9.0" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: com.rpl/specter:1.0.4" level="project" />
|
<orderEntry type="library" name="Leiningen: com.rpl/specter:1.0.4" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: commons-codec:1.10" level="project" />
|
<orderEntry type="library" name="Leiningen: commons-codec:1.10" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: commons-fileupload:1.3.3" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: commons-io:2.5" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: compojure:1.6.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: crypto-equality:1.0.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: crypto-random:1.2.0" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: environ:1.1.0" level="project" />
|
<orderEntry type="library" name="Leiningen: environ:1.1.0" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: fipp:0.6.10" level="project" />
|
<orderEntry type="library" name="Leiningen: fipp:0.6.10" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: flare:0.2.9" level="project" />
|
<orderEntry type="library" name="Leiningen: flare:0.2.9" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: http-kit:2.3.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: instaparse:1.4.8" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: io.aviso/pretty:0.1.34" level="project" />
|
<orderEntry type="library" name="Leiningen: io.aviso/pretty:0.1.34" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: javax.servlet/javax.servlet-api:3.1.0" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: joda-time:2.9.7" level="project" />
|
<orderEntry type="library" name="Leiningen: joda-time:2.9.7" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: marick/clojure-commons:3.0.0" level="project" />
|
<orderEntry type="library" name="Leiningen: marick/clojure-commons:3.0.0" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: marick/suchwow:6.0.0" level="project" />
|
<orderEntry type="library" name="Leiningen: marick/suchwow:6.0.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: medley:1.0.0" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: midje:1.9.1" level="project" />
|
<orderEntry type="library" name="Leiningen: midje:1.9.1" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: mvxcvi/arrangement:1.1.1" level="project" />
|
<orderEntry type="library" name="Leiningen: mvxcvi/arrangement:1.1.1" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: mvxcvi/puget:1.0.2" level="project" />
|
<orderEntry type="library" name="Leiningen: mvxcvi/puget:1.0.2" level="project" />
|
||||||
@@ -53,7 +67,10 @@
|
|||||||
<orderEntry type="library" name="Leiningen: org.tcrawley/dynapath:1.0.0" level="project" />
|
<orderEntry type="library" name="Leiningen: org.tcrawley/dynapath:1.0.0" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: potemkin:0.4.3" level="project" />
|
<orderEntry type="library" name="Leiningen: potemkin:0.4.3" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: riddley:0.1.12" level="project" />
|
<orderEntry type="library" name="Leiningen: riddley:0.1.12" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: ring/ring-codec:1.1.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: ring/ring-core:1.6.3" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: slingshot:0.12.2" level="project" />
|
<orderEntry type="library" name="Leiningen: slingshot:0.12.2" level="project" />
|
||||||
<orderEntry type="library" name="Leiningen: swiss-arrows:1.0.0" level="project" />
|
<orderEntry type="library" name="Leiningen: swiss-arrows:1.0.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Leiningen: tigris:0.1.1" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
+9
-1
@@ -4,7 +4,15 @@
|
|||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
||||||
:dependencies [[org.clojure/clojure "1.9.0"]
|
:dependencies [[org.clojure/clojure "1.9.0"]
|
||||||
[org.clojure/core.async "0.4.474"]]
|
[org.clojure/core.async "0.4.474"]
|
||||||
|
;; web
|
||||||
|
[http-kit "2.3.0"]
|
||||||
|
[compojure "1.6.1"]
|
||||||
|
[javax.servlet/javax.servlet-api "3.1.0"]
|
||||||
|
|
||||||
|
;;utils
|
||||||
|
[slingshot "0.12.2"]
|
||||||
|
[cheshire "5.8.0"]]
|
||||||
:java-source-paths ["src/java"]
|
:java-source-paths ["src/java"]
|
||||||
:main ^:skip-aot book.core
|
:main ^:skip-aot book.core
|
||||||
:target-path "target/%s"
|
:target-path "target/%s"
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
(ns book.cli
|
||||||
|
(:require [book.match :refer [sell?]]
|
||||||
|
[book.util :refer :all]
|
||||||
|
[book.exchange :refer [empty-book process-orders create-exchange-for-security]]
|
||||||
|
[book.order] ;; for spec side effect
|
||||||
|
[slingshot.slingshot :refer [try+ throw+]]
|
||||||
|
[clojure.edn :as edn]
|
||||||
|
[clojure.core.async :refer [chan go >!! <!!]]
|
||||||
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
|
|
||||||
|
(def incoming-order-channel (chan))
|
||||||
|
|
||||||
|
;(def trades-channel (chan))
|
||||||
|
;
|
||||||
|
;(def new-book-order-channel (chan))
|
||||||
|
|
||||||
|
(defn print-chan [prefix c]
|
||||||
|
(loop [shit (<!! c)]
|
||||||
|
(println prefix shit)
|
||||||
|
(recur (<!! c))))
|
||||||
|
|
||||||
|
;(def master-book {:sell (create-sell-book)
|
||||||
|
; :buy (create-buy-book)})
|
||||||
|
|
||||||
|
;;; repl things.
|
||||||
|
(defn read-order []
|
||||||
|
(try
|
||||||
|
(print "$ ")
|
||||||
|
(let [order (edn/read-string (read-line))
|
||||||
|
valid? (s/valid? :book.order/order order)]
|
||||||
|
(if valid? order nil))
|
||||||
|
(catch Exception e nil)))
|
||||||
|
|
||||||
|
(def order-ids (atom -1))
|
||||||
|
|
||||||
|
|
||||||
|
(defn add-id-to-order [order]
|
||||||
|
(assoc order :book.order/id (swap! order-ids inc)))
|
||||||
|
|
||||||
|
|
||||||
|
(defn -main [& args]
|
||||||
|
(let [initial-book empty-book
|
||||||
|
incoming-order-channel (chan)
|
||||||
|
[trades-channel new-book-order-channel] (create-exchange-for-security initial-book incoming-order-channel)]
|
||||||
|
(go (print-chan "trade > " trades-channel))
|
||||||
|
(go (print-chan "order > " new-book-order-channel))
|
||||||
|
(loop [order (read-order)]
|
||||||
|
(if (some? order)
|
||||||
|
(do
|
||||||
|
(let [order-with-id (add-id-to-order order)]
|
||||||
|
(>!! incoming-order-channel order-with-id)
|
||||||
|
(println "\n\norder accepted with id: " (:book.order/id order-with-id))))
|
||||||
|
|
||||||
|
(println "invalid order"))
|
||||||
|
(recur (read-order)))))
|
||||||
+7
-77
@@ -1,80 +1,10 @@
|
|||||||
(ns book.core
|
(ns book.core
|
||||||
(:require [book.match :refer [sell?
|
(:require [book.cli]
|
||||||
create-buy-book
|
[book.web])
|
||||||
create-sell-book
|
|
||||||
match-order-in-book]]
|
|
||||||
[book.util :refer :all]
|
|
||||||
[book.order] ;; for spec side effect
|
|
||||||
[clojure.edn :as edn]
|
|
||||||
[clojure.core.async :refer [chan go >!! <!!]]
|
|
||||||
[clojure.spec.alpha :as s])
|
|
||||||
(:gen-class))
|
(:gen-class))
|
||||||
|
|
||||||
(def incoming-order-channel (chan))
|
(defn -main [& argv]
|
||||||
|
(case (first argv)
|
||||||
(def trades-channel (chan))
|
"web" (apply book.web/-main (rest argv))
|
||||||
|
"cli" (apply book.cli/-main (rest argv))
|
||||||
(def new-book-order-channel (chan))
|
(println "First argument must be web or cli")))
|
||||||
|
|
||||||
(defn print-chan [prefix c]
|
|
||||||
(loop [shit (<!! c)]
|
|
||||||
(println prefix shit)
|
|
||||||
(recur (<!! c))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(def master-book {:sell (create-sell-book)
|
|
||||||
:buy (create-buy-book)})
|
|
||||||
|
|
||||||
;
|
|
||||||
;(defn process-buy-order [order]
|
|
||||||
; (let [[x y x] (match-order-in-book @buy-book order)]))
|
|
||||||
|
|
||||||
|
|
||||||
;;; repl things.
|
|
||||||
(defn read-order []
|
|
||||||
(try
|
|
||||||
(print "$ ")
|
|
||||||
(let [order (edn/read-string (read-line))
|
|
||||||
valid? (s/valid? :book.order/order order)]
|
|
||||||
(if valid? order nil))
|
|
||||||
(catch Exception e nil)))
|
|
||||||
|
|
||||||
(def order-ids (atom -1))
|
|
||||||
|
|
||||||
(defn add-id-to-order [order]
|
|
||||||
(assoc order :book.order/id (swap! order-ids inc)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn process-orders [master-book orders-channel trades-channel new-book-order-channel]
|
|
||||||
(loop [order (<!! orders-channel)
|
|
||||||
{sell-book :sell buy-book :buy} master-book]
|
|
||||||
(if (sell? order)
|
|
||||||
(do
|
|
||||||
(let [[trades new-buy-book leftover-order] (match-order-in-book buy-book order)
|
|
||||||
new-sell-book (if leftover-order (conj sell-book) leftover-order)]
|
|
||||||
(when (seq trades) (>!! trades-channel trades))
|
|
||||||
(when leftover-order (>!! new-book-order-channel leftover-order))
|
|
||||||
(recur (<!! orders-channel) {:sell new-sell-book :buy new-buy-book})))
|
|
||||||
(do
|
|
||||||
(let [[trades new-sell-book leftover-order] (match-order-in-book sell-book order)
|
|
||||||
new-buy-book (if leftover-order (conj buy-book) leftover-order)]
|
|
||||||
(when (seq trades) (>!! trades-channel trades))
|
|
||||||
(when leftover-order (>!! new-book-order-channel leftover-order))
|
|
||||||
(recur (<!! orders-channel) {:sell new-sell-book :buy new-buy-book}))))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn -main [& args]
|
|
||||||
(println "enter orders in edn format.")
|
|
||||||
(go (print-chan "trade > " trades-channel))
|
|
||||||
(go (print-chan "order > " new-book-order-channel))
|
|
||||||
(go (process-orders master-book incoming-order-channel trades-channel new-book-order-channel))
|
|
||||||
(loop [order (read-order)]
|
|
||||||
(if (some? order)
|
|
||||||
(do
|
|
||||||
(let [order-with-id (add-id-to-order order)]
|
|
||||||
(>!! incoming-order-channel order-with-id)
|
|
||||||
(println "\n\norder accepted with id: " (:book.order/id order-with-id))))
|
|
||||||
|
|
||||||
(println "invalid order"))
|
|
||||||
(recur (read-order))))
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
(ns book.exchange
|
||||||
|
(:require [book.match :refer [sell?
|
||||||
|
create-buy-book
|
||||||
|
create-sell-book
|
||||||
|
match-order-in-book]]
|
||||||
|
[book.util :refer :all]
|
||||||
|
[clojure.core.async :refer [chan go >!! <!!]]))
|
||||||
|
|
||||||
|
(def empty-book {:sell (create-sell-book) :buy (create-buy-book)})
|
||||||
|
|
||||||
|
|
||||||
|
(defn process-abstract-sell [order reference-book same-type-book trades-channel new-book-order-channel]
|
||||||
|
(let [[trades new-reference-book leftover-order] (match-order-in-book reference-book order)
|
||||||
|
new-same-type-book (if leftover-order (conj same-type-book leftover-order) leftover-order)]
|
||||||
|
(when (seq trades) (doseq [trade trades] (>!! trades-channel trade)))
|
||||||
|
(when leftover-order (>!! new-book-order-channel leftover-order))
|
||||||
|
[new-reference-book new-same-type-book]))
|
||||||
|
|
||||||
|
|
||||||
|
(defn process-sell-order [order {sell-book :sell buy-book :buy} trades-channel new-book-order-channel]
|
||||||
|
(let [[new-buy-book new-sell-book] (process-abstract-sell order buy-book sell-book trades-channel new-book-order-channel)]
|
||||||
|
{:sell new-sell-book :buy new-buy-book}))
|
||||||
|
|
||||||
|
(defn process-buy-order [order {sell-book :sell buy-book :buy} trades-channel new-book-order-channel]
|
||||||
|
(let [[new-sell-book new-buy-book] (process-abstract-sell order sell-book buy-book trades-channel new-book-order-channel)]
|
||||||
|
{:sell new-sell-book :buy new-buy-book}))
|
||||||
|
|
||||||
|
(defn process-orders [master-book orders-channel trades-channel new-book-order-channel]
|
||||||
|
(loop [order (<!! orders-channel)
|
||||||
|
book master-book]
|
||||||
|
(let [process-order (if (sell? order) process-sell-order process-buy-order)
|
||||||
|
new-book (process-order order book trades-channel new-book-order-channel)]
|
||||||
|
(recur (<!! orders-channel) new-book))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn create-exchange-for-security [initial-book incoming-order-channel]
|
||||||
|
(let [trades-channel (chan)
|
||||||
|
new-book-order-channel (chan)]
|
||||||
|
(go (process-orders initial-book incoming-order-channel trades-channel new-book-order-channel))
|
||||||
|
[trades-channel new-book-order-channel]))
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
(ns book.rest.util
|
||||||
|
(:require [cheshire.core :refer [generate-string]]
|
||||||
|
[clojure.string :refer [split starts-with? ends-with?]]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(def mime-types
|
||||||
|
[["application/json" generate-string]
|
||||||
|
["application/edn" str]])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defn create-mime-type-predicate [accept]
|
||||||
|
(let [[accept-start accept-end] (split accept #"/")]
|
||||||
|
(fn [mimetype]
|
||||||
|
(let [[start end] (split mimetype #"/")]
|
||||||
|
(and (or (= "*" accept-start) (= start accept-start))
|
||||||
|
(or (= "*" accept-end) (= end accept-end)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn get-best-serializer [request]
|
||||||
|
(let [accept (get-in request [:headers "accept"] "*/*")
|
||||||
|
accept-content-types (conj (split accept #",\s*") "*/*")
|
||||||
|
xf (comp (map create-mime-type-predicate)
|
||||||
|
(map (fn [mime-pred] (filter #(mime-pred (first %)) mime-types)))
|
||||||
|
cat
|
||||||
|
(take 1))]
|
||||||
|
(first (sequence xf accept-content-types))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn get-status [status request]
|
||||||
|
(if (nil? status)
|
||||||
|
(case (:request-method request)
|
||||||
|
:get 200
|
||||||
|
:post 201
|
||||||
|
200)
|
||||||
|
status))
|
||||||
|
|
||||||
|
(defn build-response [request {status :status body :body :as response}]
|
||||||
|
(let [[content-type serializer] (get-best-serializer request)]
|
||||||
|
{:body (serializer response)
|
||||||
|
:headers {"Content-Type" content-type}
|
||||||
|
:status (get-status status request)}))
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
(ns book.web
|
||||||
|
(:require [book.exchange :refer [empty-book]]
|
||||||
|
[org.httpkit.server :refer [run-server]]
|
||||||
|
[compojure.route :refer [not-found]]
|
||||||
|
[compojure.handler :refer [api]]
|
||||||
|
[compojure.core :refer :all]
|
||||||
|
[book.order] ;; for spec side effect
|
||||||
|
[book.rest.util :refer [build-response]]
|
||||||
|
[clojure.spec.alpha :as s]
|
||||||
|
[slingshot.slingshot :refer [try+ throw+]]
|
||||||
|
[cheshire.core :refer [generate-string]]
|
||||||
|
[clojure.edn :as edn]))
|
||||||
|
|
||||||
|
|
||||||
|
(def order-id (atom -1))
|
||||||
|
|
||||||
|
|
||||||
|
(defn api-description [req]
|
||||||
|
(let [body {"/api/1/securities" "list all securities."
|
||||||
|
"/api/1/book" "For all information about the book."}]
|
||||||
|
(build-response req body)))
|
||||||
|
|
||||||
|
|
||||||
|
;; the api should look like...
|
||||||
|
;; trades ...
|
||||||
|
;; /:sec-id/trades/:trade-id
|
||||||
|
;; book ...
|
||||||
|
;; /:sec-id/book/:order
|
||||||
|
;;
|
||||||
|
|
||||||
|
|
||||||
|
(defn securities [books]
|
||||||
|
(fn [request]
|
||||||
|
(build-response request {:securities (keys books)})))
|
||||||
|
|
||||||
|
(defn get-security [books]
|
||||||
|
(fn [{{sec-id-str :sec-id} :route-params body :body :as request}]))
|
||||||
|
|
||||||
|
(defn validate-order [asked-order]
|
||||||
|
(if (not (s/valid? :book.order/order asked-order))
|
||||||
|
(throw+ {:status :4XX :headers {"Content-Type" "application/json"} :body "foo"}))
|
||||||
|
(assoc asked-order :book.order/id (swap! order-id inc)))
|
||||||
|
|
||||||
|
|
||||||
|
(defn get-order [body]
|
||||||
|
(try+
|
||||||
|
(-> body clojure.java.io/reader slurp edn/read-string)
|
||||||
|
(catch Exception e
|
||||||
|
(throw+ {:error-type :4XX :status 400 :body {:error "Invalid body format. Body must be edn format."}}))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn create-order [books]
|
||||||
|
(fn [{{sec-id-str :sec-id} :route-params body :body :as request}]
|
||||||
|
(try+
|
||||||
|
(let [asked-order (get-order body)
|
||||||
|
order (validate-order asked-order)
|
||||||
|
sec-id (keyword sec-id-str)
|
||||||
|
book (get books sec-id)]
|
||||||
|
(build-response request {:order order :book book}))
|
||||||
|
(catch [:error-type :4XX] e (build-response request e))
|
||||||
|
(catch [:error-type :5XX] e (build-response request e)))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn create-routes [books]
|
||||||
|
(routes
|
||||||
|
(context "/api/1" []
|
||||||
|
(GET "/" [] api-description)
|
||||||
|
(GET "/securities" [] (securities books))
|
||||||
|
(GET "/securities/:sec-id" [] (get-security books))
|
||||||
|
(POST "/securities/:sec-id" [] (create-order books)))
|
||||||
|
(not-found "not found")))
|
||||||
|
|
||||||
|
|
||||||
|
(defn -main [& args]
|
||||||
|
(let [books {:foo empty-book :bar empty-book}
|
||||||
|
api-routes (create-routes books)]
|
||||||
|
(run-server (api api-routes) {:port 8080})))
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
(ns book.core-test
|
|
||||||
(:require [midje.sweet :refer :all]))
|
|
||||||
|
|
||||||
(facts "big fact"
|
|
||||||
(fact "about trivialities"
|
|
||||||
(let [expt 3]
|
|
||||||
(inc 2) => expt
|
|
||||||
(inc 2) => expt))
|
|
||||||
|
|
||||||
(fact "about trivialities 2"
|
|
||||||
(let [expt 3]
|
|
||||||
(inc 2) => expt
|
|
||||||
(inc 2) => expt)))
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
(ns book.exchange-test
|
||||||
|
(:require [midje.sweet :refer :all]
|
||||||
|
[book.exchange :refer :all]
|
||||||
|
[book.match :refer [create-buy-book
|
||||||
|
create-sell-book]]
|
||||||
|
[clojure.core.async :refer [chan go >!! <!!]]))
|
||||||
|
|
||||||
|
(facts "the exchange as an whole"
|
||||||
|
(fact "sell order followed by a buy order trivialities "
|
||||||
|
(let [incoming-order-channel (chan)
|
||||||
|
trades-channel (chan)
|
||||||
|
new-book-order-channel (chan)
|
||||||
|
master-book {:sell (create-sell-book) :buy (create-buy-book)}]
|
||||||
|
(go (process-orders master-book incoming-order-channel trades-channel new-book-order-channel))
|
||||||
|
(>!! incoming-order-channel {:type :sell :quantity 10 :price 2})
|
||||||
|
(<!! new-book-order-channel) => {:type :sell :quantity 10 :price 2}
|
||||||
|
(>!! incoming-order-channel {:type :buy :quantity 20 :price 2})
|
||||||
|
(<!! trades-channel) => #:book.order{:book-id nil
|
||||||
|
:order-id nil
|
||||||
|
:price 2
|
||||||
|
:quantity 10
|
||||||
|
:type :sell}
|
||||||
|
(<!! new-book-order-channel) => {:type :buy :quantity 10 :price 2})))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
(ns book.rest.util-test
|
||||||
|
(:require [book.rest.util :refer [build-response]]
|
||||||
|
[midje.sweet :refer :all]
|
||||||
|
[clojure.test :refer :all]))
|
||||||
|
|
||||||
|
(defn expt-response [body content-type status]
|
||||||
|
{:body body
|
||||||
|
:headers {"Content-Type" content-type}
|
||||||
|
:status status})
|
||||||
|
|
||||||
|
(facts "the building the response"
|
||||||
|
(fact "building the response in edn"
|
||||||
|
(let [content-type "application/edn"
|
||||||
|
request {:headers {"accept" content-type}}
|
||||||
|
response "foo"
|
||||||
|
expt (expt-response "foo" "application/edn" 200)]
|
||||||
|
(build-response request response) => expt))
|
||||||
|
(fact "building the response in edn"
|
||||||
|
(let [content-type "application/edn"
|
||||||
|
request {:headers {"accept" content-type}}
|
||||||
|
response {:foo [1 2 3]}
|
||||||
|
expt (expt-response "{:foo [1 2 3]}" "application/edn" 200)]
|
||||||
|
(build-response request response) => expt))
|
||||||
|
(fact "building the response in edn"
|
||||||
|
(let [content-type "application/edn,application/json"
|
||||||
|
request {:headers {"accept" content-type}}
|
||||||
|
response {:foo [1 2 3]}
|
||||||
|
expt (expt-response "{:foo [1 2 3]}" "application/edn" 200)]
|
||||||
|
(build-response request response) => expt))
|
||||||
|
(fact "building the response in json"
|
||||||
|
(let [content-type "text/html,application/xhtml+xml,application/json,application/xml;q=0.9,*/*;q=0.8"
|
||||||
|
request {:headers {"accept" content-type}}
|
||||||
|
response {:foo [1 2 3]}
|
||||||
|
expt (expt-response "{\"foo\":[1,2,3]}" "application/json" 200)]
|
||||||
|
(build-response request response) => expt))
|
||||||
|
(fact "My browser should receive json"
|
||||||
|
(let [content-type "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
||||||
|
request {:headers {"accept" content-type}}
|
||||||
|
response {:foo [1 2 3]}
|
||||||
|
expt (expt-response "{\"foo\":[1,2,3]}" "application/json" 200)]
|
||||||
|
(build-response request response) => expt)))
|
||||||
|
|
||||||
|
|
||||||
Reference in new issue
Block a user