From b972e6e69f2da888689c942666b65c99a77adf56 Mon Sep 17 00:00:00 2001 From: didier amyot Date: Thu, 1 Nov 2018 19:40:17 -0400 Subject: [PATCH] something --- project.clj | 3 +- resources/config.edn | 33 +--------- src/clj/skirmish/broker/broker.clj | 2 +- src/clj/skirmish/broker/db.clj | 9 ++- src/clj/skirmish/ledger/accounts.clj | 58 +++++++++++++++-- src/clj/skirmish/ledger/core.clj | 40 ++++++------ .../skirmish/{routes.clj => routes/api.clj} | 13 ++-- src/clj/skirmish/routes/core.clj | 44 +++++++++++++ src/clj/skirmish/util.clj | 16 ----- .../wui/components/securities_page.cljs | 63 +++++++++++++++---- .../skirmish/wui/components/todo_page.cljs | 11 +--- test/clj/skirmish/broker/db_test.clj | 21 +++++++ test/clj/skirmish/ledger/test_core.clj | 22 ++++--- .../{test_routes.clj => routes/test_api.clj} | 18 +++--- test/clj/skirmish/test_util.clj | 18 ------ 15 files changed, 230 insertions(+), 141 deletions(-) rename src/clj/skirmish/{routes.clj => routes/api.clj} (84%) create mode 100644 src/clj/skirmish/routes/core.clj create mode 100644 test/clj/skirmish/broker/db_test.clj rename test/clj/skirmish/{test_routes.clj => routes/test_api.clj} (64%) diff --git a/project.clj b/project.clj index 29135f4..8575deb 100644 --- a/project.clj +++ b/project.clj @@ -13,6 +13,7 @@ [org.clojure/math.combinatorics "0.1.4"] [com.datomic/datomic-free "0.9.5697"] [com.google.guava/guava "22.0"] + [javax.xml.bind/jaxb-api "2.2.11"] ;; server [aero "1.1.3"] @@ -64,7 +65,6 @@ :min-lein-version "2.5.0" :uberjar-name "skirmish.jar" :main skirmish.core - :jvm-opts ["--add-modules" "java.xml.bind"] :clean-targets ^{:protect false} [:target-path [:cljsbuild :builds :app :compiler :output-dir] @@ -128,6 +128,7 @@ :profiles {:dev {:repl-options {:init-ns skirmish.wui.repl :nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]} + :java-source-paths ["src/java"] :dependencies [[midje "1.9.1"] [stylefruits/gniazdo "1.0.1"] ;; only used in benchmark diff --git a/resources/config.edn b/resources/config.edn index 9f07c79..1a48ce0 100644 --- a/resources/config.edn +++ b/resources/config.edn @@ -6,7 +6,7 @@ :instrument-spec true :datomic - {:transactor-url "datomic:free://localhost:4334/skirmish"} + {:transactor-url "datomic:free://localhost:4334/skirmish.ledger"} ;; all the kafka configuration goes bellow. :kafka @@ -40,40 +40,9 @@ :max-ws 524288 :datomic {:transactor-url "datomic:free://localhost:4334/skirmish.broker"}} - :wui {:port #long #or [#env WUI_PORT 3000]} - ;; list of tradable securities - :securities - [{:sec-id :dapm - :currency :dapm - :symbol "ლ" - :name "didier amyot paper money" - :interest-rate 1.1 ;; 10% per day - :emitter "emitter publick key" - :description "The default currency."} - - {:sec-id :foo - :currency :dapm - :name "the foo company" - :description "Sell names to developer."} - - {:sec-id :bar - :currency :dapm - :name "bar international" - :description "Steal company."} - - {:sec-id :toto - :currency :dapm - :name "La compagnie des toto" - :description "Serait trop long pour ecrire ici."} - - {:sec-id :tata - :currency :dapm - :name "Unicorn startup" - :description "ambition: conquerir le monde!"}] - ;; stupid parameters about benchmarking tools :benchmark { :number-of-requests-per-securities 30}} diff --git a/src/clj/skirmish/broker/broker.clj b/src/clj/skirmish/broker/broker.clj index 2a9520e..f6aae79 100644 --- a/src/clj/skirmish/broker/broker.clj +++ b/src/clj/skirmish/broker/broker.clj @@ -50,7 +50,7 @@ :where [_ :skirmish.broker.user/email ?email]] db) xf (comp cat (map #(hash-map :email % :url (str "/api/1/users/" %))))] (build-response request - (doall ((sequence xf emails))))) + {:users (doall (sequence xf emails))})) (catch [:error-type :4XX] e (build-response request e)) (catch [:error-type :5XX] e (build-response request e))))) diff --git a/src/clj/skirmish/broker/db.clj b/src/clj/skirmish/broker/db.clj index fe85b0f..aee683c 100644 --- a/src/clj/skirmish/broker/db.clj +++ b/src/clj/skirmish/broker/db.clj @@ -9,8 +9,8 @@ :db/fn (d/function {:lang "clojure" :requires ['[slingshot.slingshot]] :params '[db email] - :code '(let [existing-user (d/pull db '[:db/id] [:skirmish.broker.user/email email - :skirmish.broker.user/accounts []])] + :code '(let [existing-user (d/pull db '[:db/id] [:skirmish.broker.user/email email])] + ;:skirmish.broker.user/accounts []])] (when (-> existing-user :db/id some?) (slingshot.slingshot/throw+ {:error-type :4XX :status 400 :body {:error "A user with this email already exists."}})) [#:skirmish.broker.user{:email email}])})}]) @@ -27,7 +27,7 @@ :db/ident :skirmish.broker.account/sec-id :db/valueType :db.type/keyword :db/cardinality :db.cardinality/one - :db/doc "The security if of the account."} + :db/doc "The security id of the account."} { :db/ident :skirmish.broker.account/private-key :db/valueType :db.type/string @@ -44,10 +44,9 @@ :db/doc "The email of the user; used as id."} { :db/ident :skirmish.broker.user/accounts - :db/unique :db.unique/identity :db/valueType :db.type/ref :db/cardinality :db.cardinality/many - :db/doc "The email of the user; used as id."}]) + :db/doc "The list of the accounts own by the user."}]) (def schema (-> [] diff --git a/src/clj/skirmish/ledger/accounts.clj b/src/clj/skirmish/ledger/accounts.clj index ff9b0b1..5e11933 100644 --- a/src/clj/skirmish/ledger/accounts.clj +++ b/src/clj/skirmish/ledger/accounts.clj @@ -111,10 +111,56 @@ (concat create-securities) (concat print-securities))) -(defn create-connection [uri] - (let [new-db? (d/create-database uri) - conn (d/connect uri)] - ;(when new-db? - @(d/transact conn schema) - conn)) + +(defn add-default-currencies [conn] + (let [dapm #:skirmish.security{:sec-id :dapm + :name "didier amyot paper money" + :type :currency + :description "The official currency of the 'Skirmish Shitty Exchange'." + :emitter "dapm private key" + :number-of-decimal 2 + :symbol "რ" + :interest-rate 10} + apbm #:skirmish.security{:sec-id :apbm + :name "apache beam" + :type :equity + :description "Unified programming model to define and execute data processing pipelines, including ETL, batch and stream (continuous) processing." + :emitter "apbm private key" + :number-of-decimal 0} + apac #:skirmish.security{:sec-id :apac + :name "apache accumulo" + :type :equity + :description "A sorted, distributed key/value store that provides robust, scalable data storage and retrieval." + :emitter "apac private key" + :number-of-decimal 0} + apax #:skirmish.security{:sec-id :apax + :name "apache apex" + :type :equity + :description "Enterprise-grade unified stream and batch processing engine." + :emitter ":apax private key" + :number-of-decimal 0} + apdr #:skirmish.security{:sec-id :apdr + :name "apache drill" + :type :equity + :description "Schema-free SQL Query Engine for Hadoop, NoSQL and Cloud Storage." + :emitter ":apdr private key" + :number-of-decimal 0} + apmh #:skirmish.security{:sec-id :apmh + :name "apache mahout" + :type :equity + :description "For Creating Scalable Performant Machine Learning Applications." + :emitter ":apmh private key" + :number-of-decimal 0}] + @(d/transact conn [dapm apbm apac apax apdr apmh]))) + +(defn create-connection + ([uri init-when-new?] + (let [new-db? (d/create-database uri) + conn (d/connect uri)] + @(d/transact conn schema) + (if (and init-when-new? new-db?) + (add-default-currencies conn)) + conn)) + ([uri] + (create-connection uri true))) diff --git a/src/clj/skirmish/ledger/core.clj b/src/clj/skirmish/ledger/core.clj index d5c8e12..b08fec8 100644 --- a/src/clj/skirmish/ledger/core.clj +++ b/src/clj/skirmish/ledger/core.clj @@ -1,5 +1,6 @@ (ns skirmish.ledger.core (:require [org.httpkit.server :refer [run-server]] + [skirmish.routes.core :as routes] [compojure.handler :refer [api]] [skirmish.util :refer [block-thread]] [slingshot.slingshot :refer [try+ throw+]] @@ -9,7 +10,7 @@ [skirmish.ledger.accounts] [datomic.api :as d] [taoensso.timbre :as timbre] - [compojure.core :refer :all] + [compojure.core :as compojure] [clojure.spec.alpha :as s] [ring.middleware.cors :refer [wrap-cors]])) @@ -88,10 +89,10 @@ :type type_ :description description})) + (defn get-security-from-db [conn sec-id] (let [db (d/db conn) e (d/pull db '[*] [:skirmish.security/sec-id sec-id])] - (println (str e)) (if (-> e :db/id nil?) (throw+ {:error-type :4XX :status 404 :body {:error "Security not found."}}) (prettify-security e db)))) @@ -100,13 +101,14 @@ "Create a fresh new security." (fn [{body :body :as request}] (try+ - (let [[sec-id interest-rate] (-> body get-body get-new-security)] - @(d/transact conn [[:skirmish.ledger/create-security sec-id interest-rate]]) + (let [[sec-id interest-rate] (-> body get-body get-new-security) + new-sec @(d/transact conn [[:skirmish.ledger/create-security sec-id interest-rate]])] (build-response request {:body {:success true} :headers {"location" (str "/api/1" "/ledger/securities/" (name sec-id))}})) (catch [:error-type :4XX] e (build-response request e)) (catch [:error-type :5XX] e (build-response request e))))) + (defn get-security [conn] "Returns the security." (fn [{{sec-id-str :sec-id} :route-params :as request}] @@ -126,7 +128,7 @@ (defn get-available-securities-body [securities] - (let [sec-id->url #(str "/api/1/ledger/securities/" (name %)) + (let [sec-id->url #(routes/get-path-for :ledger/security {:sec-id (name %)}) to-security-description #(hash-map :sec-id % :url (sec-id->url %)) xf (comp cat (map to-security-description)) securities-info (sequence xf securities)];; @@ -161,7 +163,7 @@ (defn get-available-accounts-body [accounts] - (let [sec-id->url #(str "/api/1/ledger/accounts/" (name %)) + (let [sec-id->url #(routes/get-path-for :ledger/account {:account-id (name %)}) to-security-description #(hash-map :account-public-key % :url (sec-id->url %)) xf (comp cat (map to-security-description)) securities-info (sequence xf accounts)];; @@ -180,25 +182,25 @@ (build-response request body))) -(defn create-routes-for-ledger [securities conn] - (routes - (context "/api/1/ledger" [] - (GET "/" get-api-description) - (GET "/accounts" [] (get-available-accounts conn)) - (GET "/accounts/:account-id" [] (get-account conn)) - (GET "/securities" [] (get-available-securities conn)) ;; done - (POST "/securities" [] (create-security conn)) ;; done - (GET "/securities/:sec-id" [] (get-security conn)) ;; done - (PUT "/securities/:sec-id" [] (update-security conn)) ;; not done - (POST "/securities/:sec-id" [] (emit-securities conn))) ;; done +(defn create-routes-for-ledger [conn] + (compojure/routes + ;; (routes/get-context :ledger) + (routes/context :ledger [] + (routes/GET :ledger/home [] get-api-description) + (routes/GET :ledger/accounts [] (get-available-accounts conn)) + (routes/GET :ledger/account [] (get-account conn)) + (routes/GET :ledger/securities [] (get-available-securities conn)) ;; done + (routes/POST :ledger/securities [] (create-security conn)) ;; done + (routes/GET :ledger/security [] (get-security conn)) ;; done + (routes/PUT :ledger/security [] (update-security conn)) ;; not done + (routes/POST :ledger/security [] (emit-securities conn))) ;; done (not-found "not found"))) (defn -main [config securities-api exchange-apis] (let [ledger-config (:ledger-server config) conn (skirmish.ledger.accounts/create-connection (-> config :datomic :transactor-url)) - api-routes (create-routes-for-ledger (:securities config) conn)] - + api-routes (create-routes-for-ledger conn)] (timbre/info "Running skirmish.ledger.core server with config: " ledger-config) (run-server (-> api-routes api cors-middleware) diff --git a/src/clj/skirmish/routes.clj b/src/clj/skirmish/routes/api.clj similarity index 84% rename from src/clj/skirmish/routes.clj rename to src/clj/skirmish/routes/api.clj index 057f4c9..b82c1fa 100644 --- a/src/clj/skirmish/routes.clj +++ b/src/clj/skirmish/routes/api.clj @@ -1,4 +1,4 @@ -(ns skirmish.routes) +(ns skirmish.routes.api) (defn get-app-for [all-routes k] "An app consists on a name, a prefix and some routes." @@ -16,16 +16,15 @@ "Returns what compojure expects to have." (->> k (get-route-for all-routes) :path)) -(defn replace-part [part params] +(defn- replace-part [part params] (if (clojure.string/starts-with? part ":") (-> part (subs 1) keyword params) part)) -(defn path-for [p params] +(defn- path-for [p params] (let [parts (clojure.string/split p #"/")] (clojure.string/join "/" (map #(replace-part % params) parts)))) - (defn get-context [all-routes c] (let [get-app #(get-app-for all-routes %)] (-> c @@ -34,7 +33,6 @@ get-app :path))) - (defn get-path-for "Returns a link to a location by name." ([all-routes k] @@ -42,6 +40,7 @@ ([all-routes k params] (let [app (get-app-for all-routes k) route (get-route-for all-routes k) - p (str (:path app) (:path route))] - (path-for p params)))) + p (str (:path app) (:path route)) + domain (get app :domain "")] + (str domain (path-for p params))))) diff --git a/src/clj/skirmish/routes/core.clj b/src/clj/skirmish/routes/core.clj new file mode 100644 index 0000000..172e3d8 --- /dev/null +++ b/src/clj/skirmish/routes/core.clj @@ -0,0 +1,44 @@ +(ns skirmish.routes.core + (:require [skirmish.routes.api :as routes-api] + [compojure.core :as compojure])) + + +(def ledger-routes { + :name :ledger + :domain "http://localhost:1604" ;; should somehow be in some config + :path "/api/1/ledger" + :routes [{:name :home :path "/"} + {:name :accounts :path "/accounts"} + {:name :account :path "/accounts/:account-id"} + {:name :securities :path "/securities"} + {:name :security :path "/securities/:sec-id"}]}) + +(def all-routes [ledger-routes]) + +(def get-context (partial routes-api/get-context all-routes)) + +(def get-compojure-path (partial routes-api/get-compojure-path all-routes)) + +(def get-path-for (partial routes-api/get-path-for all-routes)) + +(defmacro GET [path args & body] + (compojure/compile-route :get + (get-compojure-path path) + args + body)) + +(defmacro POST [path args & body] + (compojure/compile-route :post + (get-compojure-path path) + args + body)) + +(defmacro PUT [path args & body] + (compojure/compile-route :put + (get-compojure-path path) + args + body)) + +(defmacro context [path args & routes] + (let [resolved-path (get-context path)] + (concat `(compojure/context ~resolved-path ~args) routes))) diff --git a/src/clj/skirmish/util.clj b/src/clj/skirmish/util.clj index d34a247..63ebfe4 100644 --- a/src/clj/skirmish/util.clj +++ b/src/clj/skirmish/util.clj @@ -11,19 +11,3 @@ (defn block-thread [] "Block the current thread until chuck norris gets weaker." (async/! ret sec))) + (recur url))) + ret)) + +(defn get-securities [a-securities] + (let [securities (get-all-securities)] + (async/go-loop [security (async/ email))); \ No newline at end of file diff --git a/test/clj/skirmish/ledger/test_core.clj b/test/clj/skirmish/ledger/test_core.clj index b6737bc..38c2161 100644 --- a/test/clj/skirmish/ledger/test_core.clj +++ b/test/clj/skirmish/ledger/test_core.clj @@ -24,7 +24,7 @@ (defn create-conn [] (let [mem-url "datomic:mem://skirmish"] (d/delete-database mem-url) - (create-connection mem-url))) + (create-connection mem-url false))) @@ -40,7 +40,7 @@ (def mock-currencies [[:zimbabwean-dollar 1000000 :currency "zimbabwean dollar" "rot13" "zd"]]) - +;; (defn create-some-securities [conn] (let [cs (create-security conn) create-security-1 {:body (edn->stream (get mock-securities 0)) :headers {"accept" "application/edn"}} @@ -126,7 +126,15 @@ empty-res => (spec-check ::ok) one-res => (spec-check ::ok) (body empty-res) => {:securities []} - (body one-res) => {:securities [{:sec-id :new-currency :url "/api/1/ledger/securities/new-currency"}]}))) + (body one-res) => {:securities [{:sec-id :new-currency :url "http://localhost:1604/api/1/ledger/securities/new-currency"}]})) + + (fact "it should add default currencies when creating new db" + (let [mem-url "datomic:mem://skirmish-in-test" + _ (d/delete-database mem-url) + conn (create-connection mem-url true) + request {:route-params {} :headers {"accept" "application/edn"}} + resp ((get-available-securities conn) request)] + (->> resp body :securities (map :sec-id) sort) => [:apac :apax :apbm :apdr :apmh :dapm]))) (facts "about the emitting securities" @@ -162,10 +170,10 @@ (fact "we should be able to get list of all accounts" (let [conn (create-some-securities-and-accounts (create-conn)) req {:route-params {} :headers {"accept" "application/edn"}} - expt [{:account-public-key "1-sec-1" :url "/api/1/ledger/accounts/1-sec-1"} - {:account-public-key "1-sec-2" :url "/api/1/ledger/accounts/1-sec-2"} - {:account-public-key "2-sec-1" :url "/api/1/ledger/accounts/2-sec-1"} - {:account-public-key "2-sec-2" :url "/api/1/ledger/accounts/2-sec-2"}]] + expt [{:account-public-key "1-sec-1" :url "http://localhost:1604/api/1/ledger/accounts/1-sec-1"} + {:account-public-key "1-sec-2" :url "http://localhost:1604/api/1/ledger/accounts/1-sec-2"} + {:account-public-key "2-sec-1" :url "http://localhost:1604/api/1/ledger/accounts/2-sec-1"} + {:account-public-key "2-sec-2" :url "http://localhost:1604/api/1/ledger/accounts/2-sec-2"}]] ((get-available-accounts conn) req) => (spec-check ::ok) (-> ((get-available-accounts conn) req) body :accounts sec->hash-set) => (sec->hash-set expt))) diff --git a/test/clj/skirmish/test_routes.clj b/test/clj/skirmish/routes/test_api.clj similarity index 64% rename from test/clj/skirmish/test_routes.clj rename to test/clj/skirmish/routes/test_api.clj index 914c053..3bd9be6 100644 --- a/test/clj/skirmish/test_routes.clj +++ b/test/clj/skirmish/routes/test_api.clj @@ -1,19 +1,21 @@ -(ns skirmish.test-routes +(ns skirmish.routes.test-api (:require [midje.sweet :refer :all] - [skirmish.routes :refer :all])) + [skirmish.routes.api :refer :all])) (def my-ledger-routes { :name :ledger - :domain "http://localhost:1604" ;; should somehow be in some config :path "/api/1/ledger" :routes [{:name :home :path "/"} {:name :accounts :path "/accounts"} {:name :account :path "/accounts/:account-id"}]}) - -(def my-all-routes - [my-ledger-routes]) +(def wui-routes { + :name :wui + :domain "http://localhost:1534" + :path "/api/1/wui" + :routes [{:name :home :path "/home"}]}) +(def my-all-routes [my-ledger-routes wui-routes]) (facts "About routes" (fact "it should be easy to get routes" @@ -21,8 +23,8 @@ (fact "it should be able to retrieve routes" (get-path-for my-all-routes :ledger/accounts) => "/api/1/ledger/accounts" - (get-path-for my-all-routes :ledger/account {:account-id "one-two"}) => "/api/1/ledger/accounts/one-two") + (get-path-for my-all-routes :ledger/account {:account-id "one-two"}) => "/api/1/ledger/accounts/one-two" + (get-path-for my-all-routes :wui/home) => "http://localhost:1534/api/1/wui/home") (fact "it should be able to retrieve the contect" (get-context my-all-routes :ledger) => "/api/1/ledger")) -;; \ No newline at end of file diff --git a/test/clj/skirmish/test_util.clj b/test/clj/skirmish/test_util.clj index 1ca9ada..706544f 100644 --- a/test/clj/skirmish/test_util.clj +++ b/test/clj/skirmish/test_util.clj @@ -4,21 +4,3 @@ ;; midje testing -(facts "About events overlapping" - (let [evt-1 #:calendar.event{:start 10 :end 15} - evt-2 #:calendar.event{:start 12 :end 17} - evt-3 #:calendar.event{:start 15 :end 25} - - evt-4 #:calendar.event{:start 30 :end 40} - evt-5 #:calendar.event{:start 33 :end 34}] - - (fact "about edge cases" - (get-overlapping-events nil) => empty? - (get-overlapping-events []) => empty?) - - (fact "about regular situations" - (get-overlapping-events [evt-1 evt-2]) => [[evt-1 evt-2]] - (get-overlapping-events [evt-1 evt-2 evt-3]) => [[evt-1 evt-2] [evt-2 evt-3]] - (get-overlapping-events [evt-4 evt-5]) => [[evt-4 evt-5]]))) - -;; \ No newline at end of file