diff --git a/README.md b/README.md index e9700d73..a13dfda2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A friendly data-driven router for Clojure(Script). * Extendable * [Fast](https://metosin.github.io/reitit/performance.html) -See [Issues](https://github.com/metosin/reitit/issues) for roadmap. +See the [full documentation](https://metosin.github.io/reitit/) for details. ## Latest version @@ -54,19 +54,23 @@ Optionally, the parts can be required separately: ; :path "/api/orders/2"} ``` -## Documentation +## More info [Check out the full documentation!](https://metosin.github.io/reitit/) +Roadmap is mostly written in [issues](https://github.com/metosin/reitit/issues). + +There is also a [#reitit](https://clojurians.slack.com/messages/reitit/) channel in [Clojurians slack](http://clojurians.net/). + ## Special thanks To all Clojure(Script) routing libs out there, expecially to [Ataraxy](https://github.com/weavejester/ataraxy), [Bide](https://github.com/funcool/bide), [Bidi](https://github.com/juxt/bidi), [Compojure](https://github.com/weavejester/compojure) and [Pedestal](https://github.com/pedestal/pedestal/tree/master/route). -Also to [Compojure-api](https://github.com/metosin/compojure-api), [Kekkonen](https://github.com/metosin/kekkonen) and [Ring-swagger](https://github.com/metosin/ring-swagger) and for the data-driven syntax, coercion & stuff. +Also to [Compojure-api](https://github.com/metosin/compojure-api), [Kekkonen](https://github.com/metosin/kekkonen), [Ring-swagger](https://github.com/metosin/ring-swagger) and [Yada](https://github.com/juxt/yada) and for ideas, coercion & stuff. -And some [Yada](https://github.com/juxt/yada) too. +And, of course, to: [Schema](https://github.com/plumatic/schema) and [clojure.spec](https://clojure.org/about/spec). ## Development instructions diff --git a/perf-test/clj/reitit/coercion_perf_test.clj b/perf-test/clj/reitit/coercion_perf_test.clj index d0351450..1376258a 100644 --- a/perf-test/clj/reitit/coercion_perf_test.clj +++ b/perf-test/clj/reitit/coercion_perf_test.clj @@ -6,11 +6,12 @@ [spec-tools.core :as st] [reitit.core :as reitit] - [reitit.core :as ring] - [reitit.coercion :as coercion] - [reitit.coercion.spec :as spec] - [reitit.coercion.protocol :as protocol] - [spec-tools.data-spec :as ds])) + [reitit.ring :as ring] + [reitit.ring.coercion :as coercion] + [reitit.ring.coercion.spec :as spec] + [reitit.ring.coercion.protocol :as protocol] + [spec-tools.data-spec :as ds] + [reitit.core :as r])) ;; ;; start repl with `lein perf repl` diff --git a/perf-test/clj/reitit/opensensors_routing_test.clj b/perf-test/clj/reitit/opensensors_routing_test.clj index cd3588dc..c3e31bcd 100644 --- a/perf-test/clj/reitit/opensensors_routing_test.clj +++ b/perf-test/clj/reitit/opensensors_routing_test.clj @@ -65,7 +65,9 @@ (comment (swagger->routes "https://api.opensensors.io/doc" false)) -(defn bench-routes [routes f] +(defrecord Request [uri path-info request-method]) + +(defn bench-routes [routes req f] (let [router (reitit/router routes) urls (valid-urls router) random-url #(rand-nth urls) @@ -74,18 +76,19 @@ dropped (int (* total 0.45))] (mapv (fn [path] - (let [time (int (* (first (:sample-mean (cc/quick-benchmark (dotimes [_ 1000] (f path)) {}))) 1e6))] + (let [request (map->Request (req path)) + time (int (* (first (:sample-mean (cc/quick-benchmark (dotimes [_ 1000] (f request)) {}))) 1e6))] (println path "=>" time "ns") [path time])) urls))) -(defn bench [routes no-paths?] +(defn bench [routes req no-paths?] (let [routes (mapv (fn [[path name]] (if no-paths? [(str/replace path #"\:" "") name] [path name])) routes) router (reitit/router routes)] - (doseq [[path time] (bench-routes routes #(reitit/match-by-path router %))] + (doseq [[path time] (bench-routes routes req #(reitit/match-by-path router %))] (println path "\t" time)))) ;; ;; Perf tests @@ -274,154 +277,154 @@ (def opensensors-compojure-routes (compojure/routes (compojure/context "/v1" [] - (compojure/context "/public" [] - (compojure/ANY "/topics/:topic" [] {:name :test/route4} handler) - (compojure/ANY "/users/:user-id" [] {:name :test/route16} handler) - (compojure/ANY "/orgs/:org-id" [] {:name :test/route18} handler)) - (compojure/context "/users/:user-id" [] - (compojure/ANY "/orgs/:org-id" [] {:name :test/route5} handler) - (compojure/ANY "/invitations" [] {:name :test/route7} handler) - (compojure/ANY "/topics" [] {:name :test/route9} handler) - (compojure/ANY "/bookmarks/followers" [] {:name :test/route10} handler) - (compojure/context "/devices" [] - (compojure/ANY "/" [] {:name :test/route15} handler) - #_(compojure/ANY "/bulk" [] {:name :test/route21} handler) - (compojure/ANY "/:client-id" [] {:name :test/route35} handler) - (compojure/ANY "/:client-id/reset-password" [] {:name :test/route49} handler)) - (compojure/ANY "/device-errors" [] {:name :test/route22} handler) - (compojure/ANY "/usage-stats" [] {:name :test/route24} handler) - (compojure/ANY "/claim-device/:client-id" [] {:name :test/route26} handler) - (compojure/ANY "/owned-orgs" [] {:name :test/route31} handler) - (compojure/ANY "/bookmark/:topic" [] {:name :test/route33} handler) - (compojure/ANY "/" [] {:name :test/route36} handler) - (compojure/ANY "/orgs" [] {:name :test/route52} handler) - (compojure/ANY "/api-key" [] {:name :test/route43} handler) - (compojure/ANY "/bookmarks" [] {:name :test/route56} handler)) - (compojure/ANY "/search/topics/:term" [] {:name :test/route6} handler) - (compojure/context "/orgs" [] - (compojure/ANY "/" [] {:name :test/route55} handler) - (compojure/context "/:org-id" [] - (compojure/context "/devices" [] - (compojure/ANY "/" [] {:name :test/route37} handler) - (compojure/ANY "/:device-id" [] {:name :test/route13} handler) - #_(compojure/ANY "/:batch/:type" [] {:name :test/route8} handler)) - (compojure/ANY "/usage-stats" [] {:name :test/route12} handler) - (compojure/ANY "/invitations" [] {:name :test/route19} handler) - (compojure/context "/members" [] - (compojure/ANY "/:user-id" [] {:name :test/route34} handler) - (compojure/ANY "/" [] {:name :test/route38} handler) - #_(compojure/ANY "/invitation-data/:user-id" [] {:name :test/route39} handler)) - (compojure/ANY "/errors" [] {:name :test/route17} handler) - (compojure/ANY "/" [] {:name :test/route42} handler) - (compojure/ANY "/confirm-membership/:token" [] {:name :test/route46} handler) - (compojure/ANY "/topics" [] {:name :test/route57} handler))) - (compojure/context "/messages" [] - (compojure/ANY "/user/:user-id" [] {:name :test/route14} handler) - (compojure/ANY "/device/:client-id" [] {:name :test/route30} handler) - (compojure/ANY "/topic/:topic" [] {:name :test/route48} handler)) - (compojure/context "/topics" [] - (compojure/ANY "/:topic" [] {:name :test/route32} handler) - (compojure/ANY "/" [] {:name :test/route54} handler)) - (compojure/ANY "/whoami" [] {:name :test/route41} handler) - (compojure/ANY "/login" [] {:name :test/route51} handler)) + (compojure/context "/public" [] + (compojure/ANY "/topics/:topic" [] {:name :test/route4} handler) + (compojure/ANY "/users/:user-id" [] {:name :test/route16} handler) + (compojure/ANY "/orgs/:org-id" [] {:name :test/route18} handler)) + (compojure/context "/users/:user-id" [] + (compojure/ANY "/orgs/:org-id" [] {:name :test/route5} handler) + (compojure/ANY "/invitations" [] {:name :test/route7} handler) + (compojure/ANY "/topics" [] {:name :test/route9} handler) + (compojure/ANY "/bookmarks/followers" [] {:name :test/route10} handler) + (compojure/context "/devices" [] + (compojure/ANY "/" [] {:name :test/route15} handler) + #_(compojure/ANY "/bulk" [] {:name :test/route21} handler) + (compojure/ANY "/:client-id" [] {:name :test/route35} handler) + (compojure/ANY "/:client-id/reset-password" [] {:name :test/route49} handler)) + (compojure/ANY "/device-errors" [] {:name :test/route22} handler) + (compojure/ANY "/usage-stats" [] {:name :test/route24} handler) + (compojure/ANY "/claim-device/:client-id" [] {:name :test/route26} handler) + (compojure/ANY "/owned-orgs" [] {:name :test/route31} handler) + (compojure/ANY "/bookmark/:topic" [] {:name :test/route33} handler) + (compojure/ANY "/" [] {:name :test/route36} handler) + (compojure/ANY "/orgs" [] {:name :test/route52} handler) + (compojure/ANY "/api-key" [] {:name :test/route43} handler) + (compojure/ANY "/bookmarks" [] {:name :test/route56} handler)) + (compojure/ANY "/search/topics/:term" [] {:name :test/route6} handler) + (compojure/context "/orgs" [] + (compojure/ANY "/" [] {:name :test/route55} handler) + (compojure/context "/:org-id" [] + (compojure/context "/devices" [] + (compojure/ANY "/" [] {:name :test/route37} handler) + (compojure/ANY "/:device-id" [] {:name :test/route13} handler) + #_(compojure/ANY "/:batch/:type" [] {:name :test/route8} handler)) + (compojure/ANY "/usage-stats" [] {:name :test/route12} handler) + (compojure/ANY "/invitations" [] {:name :test/route19} handler) + (compojure/context "/members" [] + (compojure/ANY "/:user-id" [] {:name :test/route34} handler) + (compojure/ANY "/" [] {:name :test/route38} handler) + #_(compojure/ANY "/invitation-data/:user-id" [] {:name :test/route39} handler)) + (compojure/ANY "/errors" [] {:name :test/route17} handler) + (compojure/ANY "/" [] {:name :test/route42} handler) + (compojure/ANY "/confirm-membership/:token" [] {:name :test/route46} handler) + (compojure/ANY "/topics" [] {:name :test/route57} handler))) + (compojure/context "/messages" [] + (compojure/ANY "/user/:user-id" [] {:name :test/route14} handler) + (compojure/ANY "/device/:client-id" [] {:name :test/route30} handler) + (compojure/ANY "/topic/:topic" [] {:name :test/route48} handler)) + (compojure/context "/topics" [] + (compojure/ANY "/:topic" [] {:name :test/route32} handler) + (compojure/ANY "/" [] {:name :test/route54} handler)) + (compojure/ANY "/whoami" [] {:name :test/route41} handler) + (compojure/ANY "/login" [] {:name :test/route51} handler)) (compojure/context "/v2" [] - (compojure/ANY "/whoami" [] {:name :test/route1} handler) - (compojure/context "/users/:user-id" [] - (compojure/ANY "/datasets" [] {:name :test/route2} handler) - (compojure/ANY "/devices" [] {:name :test/route25} handler) - (compojure/context "/topics" [] - (compojure/ANY "/bulk" [] {:name :test/route29} handler) - (compojure/ANY "/" [] {:name :test/route54} handler)) - (compojure/ANY "/" [] {:name :test/route45} handler)) - (compojure/context "/public" [] - (compojure/context "/projects/:project-id" [] - (compojure/ANY "/datasets" [] {:name :test/route3} handler) - (compojure/ANY "/" [] {:name :test/route27} handler)) - #_(compojure/ANY "/messages/dataset/bulk" [] {:name :test/route20} handler) - (compojure/ANY "/datasets/:dataset-id" [] {:name :test/route28} handler) - (compojure/ANY "/messages/dataset/:dataset-id" [] {:name :test/route53} handler)) - (compojure/ANY "/datasets/:dataset-id" [] {:name :test/route11} handler) - (compojure/ANY "/login" [] {:name :test/route23} handler) - (compojure/ANY "/orgs/:org-id/topics" [] {:name :test/route40} handler) - (compojure/ANY "/schemas" [] {:name :test/route44} handler) - (compojure/ANY "/topics/:topic" [] {:name :test/route47} handler) - (compojure/ANY "/topics" [] {:name :test/route50} handler)))) + (compojure/ANY "/whoami" [] {:name :test/route1} handler) + (compojure/context "/users/:user-id" [] + (compojure/ANY "/datasets" [] {:name :test/route2} handler) + (compojure/ANY "/devices" [] {:name :test/route25} handler) + (compojure/context "/topics" [] + (compojure/ANY "/bulk" [] {:name :test/route29} handler) + (compojure/ANY "/" [] {:name :test/route54} handler)) + (compojure/ANY "/" [] {:name :test/route45} handler)) + (compojure/context "/public" [] + (compojure/context "/projects/:project-id" [] + (compojure/ANY "/datasets" [] {:name :test/route3} handler) + (compojure/ANY "/" [] {:name :test/route27} handler)) + #_(compojure/ANY "/messages/dataset/bulk" [] {:name :test/route20} handler) + (compojure/ANY "/datasets/:dataset-id" [] {:name :test/route28} handler) + (compojure/ANY "/messages/dataset/:dataset-id" [] {:name :test/route53} handler)) + (compojure/ANY "/datasets/:dataset-id" [] {:name :test/route11} handler) + (compojure/ANY "/login" [] {:name :test/route23} handler) + (compojure/ANY "/orgs/:org-id/topics" [] {:name :test/route40} handler) + (compojure/ANY "/schemas" [] {:name :test/route44} handler) + (compojure/ANY "/topics/:topic" [] {:name :test/route47} handler) + (compojure/ANY "/topics" [] {:name :test/route50} handler)))) (def opensensors-compojure-api-routes (routes (context "/v1" [] - (context "/public" [] - (ANY "/topics/:topic" [] {:name :test/route4} handler) - (ANY "/users/:user-id" [] {:name :test/route16} handler) - (ANY "/orgs/:org-id" [] {:name :test/route18} handler)) - (context "/users/:user-id" [] - (ANY "/orgs/:org-id" [] {:name :test/route5} handler) - (ANY "/invitations" [] {:name :test/route7} handler) - (ANY "/topics" [] {:name :test/route9} handler) - (ANY "/bookmarks/followers" [] {:name :test/route10} handler) - (context "/devices" [] - (ANY "/" [] {:name :test/route15} handler) - #_(ANY "/bulk" [] {:name :test/route21} handler) - (ANY "/:client-id" [] {:name :test/route35} handler) - (ANY "/:client-id/reset-password" [] {:name :test/route49} handler)) - (ANY "/device-errors" [] {:name :test/route22} handler) - (ANY "/usage-stats" [] {:name :test/route24} handler) - (ANY "/claim-device/:client-id" [] {:name :test/route26} handler) - (ANY "/owned-orgs" [] {:name :test/route31} handler) - (ANY "/bookmark/:topic" [] {:name :test/route33} handler) - (ANY "/" [] {:name :test/route36} handler) - (ANY "/orgs" [] {:name :test/route52} handler) - (ANY "/api-key" [] {:name :test/route43} handler) - (ANY "/bookmarks" [] {:name :test/route56} handler)) - (ANY "/search/topics/:term" [] {:name :test/route6} handler) - (context "/orgs" [] - (ANY "/" [] {:name :test/route55} handler) - (context "/:org-id" [] - (context "/devices" [] - (ANY "/" [] {:name :test/route37} handler) - (ANY "/:device-id" [] {:name :test/route13} handler) - #_(ANY "/:batch/:type" [] {:name :test/route8} handler)) - (ANY "/usage-stats" [] {:name :test/route12} handler) - (ANY "/invitations" [] {:name :test/route19} handler) - (context "/members" [] - (ANY "/:user-id" [] {:name :test/route34} handler) - (ANY "/" [] {:name :test/route38} handler) - #_(ANY "/invitation-data/:user-id" [] {:name :test/route39} handler)) - (ANY "/errors" [] {:name :test/route17} handler) - (ANY "/" [] {:name :test/route42} handler) - (ANY "/confirm-membership/:token" [] {:name :test/route46} handler) - (ANY "/topics" [] {:name :test/route57} handler))) - (context "/messages" [] - (ANY "/user/:user-id" [] {:name :test/route14} handler) - (ANY "/device/:client-id" [] {:name :test/route30} handler) - (ANY "/topic/:topic" [] {:name :test/route48} handler)) - (context "/topics" [] - (ANY "/:topic" [] {:name :test/route32} handler) - (ANY "/" [] {:name :test/route54} handler)) - (ANY "/whoami" [] {:name :test/route41} handler) - (ANY "/login" [] {:name :test/route51} handler)) + (context "/public" [] + (ANY "/topics/:topic" [] {:name :test/route4} handler) + (ANY "/users/:user-id" [] {:name :test/route16} handler) + (ANY "/orgs/:org-id" [] {:name :test/route18} handler)) + (context "/users/:user-id" [] + (ANY "/orgs/:org-id" [] {:name :test/route5} handler) + (ANY "/invitations" [] {:name :test/route7} handler) + (ANY "/topics" [] {:name :test/route9} handler) + (ANY "/bookmarks/followers" [] {:name :test/route10} handler) + (context "/devices" [] + (ANY "/" [] {:name :test/route15} handler) + #_(ANY "/bulk" [] {:name :test/route21} handler) + (ANY "/:client-id" [] {:name :test/route35} handler) + (ANY "/:client-id/reset-password" [] {:name :test/route49} handler)) + (ANY "/device-errors" [] {:name :test/route22} handler) + (ANY "/usage-stats" [] {:name :test/route24} handler) + (ANY "/claim-device/:client-id" [] {:name :test/route26} handler) + (ANY "/owned-orgs" [] {:name :test/route31} handler) + (ANY "/bookmark/:topic" [] {:name :test/route33} handler) + (ANY "/" [] {:name :test/route36} handler) + (ANY "/orgs" [] {:name :test/route52} handler) + (ANY "/api-key" [] {:name :test/route43} handler) + (ANY "/bookmarks" [] {:name :test/route56} handler)) + (ANY "/search/topics/:term" [] {:name :test/route6} handler) + (context "/orgs" [] + (ANY "/" [] {:name :test/route55} handler) + (context "/:org-id" [] + (context "/devices" [] + (ANY "/" [] {:name :test/route37} handler) + (ANY "/:device-id" [] {:name :test/route13} handler) + #_(ANY "/:batch/:type" [] {:name :test/route8} handler)) + (ANY "/usage-stats" [] {:name :test/route12} handler) + (ANY "/invitations" [] {:name :test/route19} handler) + (context "/members" [] + (ANY "/:user-id" [] {:name :test/route34} handler) + (ANY "/" [] {:name :test/route38} handler) + #_(ANY "/invitation-data/:user-id" [] {:name :test/route39} handler)) + (ANY "/errors" [] {:name :test/route17} handler) + (ANY "/" [] {:name :test/route42} handler) + (ANY "/confirm-membership/:token" [] {:name :test/route46} handler) + (ANY "/topics" [] {:name :test/route57} handler))) + (context "/messages" [] + (ANY "/user/:user-id" [] {:name :test/route14} handler) + (ANY "/device/:client-id" [] {:name :test/route30} handler) + (ANY "/topic/:topic" [] {:name :test/route48} handler)) + (context "/topics" [] + (ANY "/:topic" [] {:name :test/route32} handler) + (ANY "/" [] {:name :test/route54} handler)) + (ANY "/whoami" [] {:name :test/route41} handler) + (ANY "/login" [] {:name :test/route51} handler)) (context "/v2" [] - (ANY "/whoami" [] {:name :test/route1} handler) - (context "/users/:user-id" [] - (ANY "/datasets" [] {:name :test/route2} handler) - (ANY "/devices" [] {:name :test/route25} handler) - (context "/topics" [] - (ANY "/bulk" [] {:name :test/route29} handler) - (ANY "/" [] {:name :test/route54} handler)) - (ANY "/" [] {:name :test/route45} handler)) - (context "/public" [] - (context "/projects/:project-id" [] - (ANY "/datasets" [] {:name :test/route3} handler) - (ANY "/" [] {:name :test/route27} handler)) - #_(ANY "/messages/dataset/bulk" [] {:name :test/route20} handler) - (ANY "/datasets/:dataset-id" [] {:name :test/route28} handler) - (ANY "/messages/dataset/:dataset-id" [] {:name :test/route53} handler)) - (ANY "/datasets/:dataset-id" [] {:name :test/route11} handler) - (ANY "/login" [] {:name :test/route23} handler) - (ANY "/orgs/:org-id/topics" [] {:name :test/route40} handler) - (ANY "/schemas" [] {:name :test/route44} handler) - (ANY "/topics/:topic" [] {:name :test/route47} handler) - (ANY "/topics" [] {:name :test/route50} handler)))) + (ANY "/whoami" [] {:name :test/route1} handler) + (context "/users/:user-id" [] + (ANY "/datasets" [] {:name :test/route2} handler) + (ANY "/devices" [] {:name :test/route25} handler) + (context "/topics" [] + (ANY "/bulk" [] {:name :test/route29} handler) + (ANY "/" [] {:name :test/route54} handler)) + (ANY "/" [] {:name :test/route45} handler)) + (context "/public" [] + (context "/projects/:project-id" [] + (ANY "/datasets" [] {:name :test/route3} handler) + (ANY "/" [] {:name :test/route27} handler)) + #_(ANY "/messages/dataset/bulk" [] {:name :test/route20} handler) + (ANY "/datasets/:dataset-id" [] {:name :test/route28} handler) + (ANY "/messages/dataset/:dataset-id" [] {:name :test/route53} handler)) + (ANY "/datasets/:dataset-id" [] {:name :test/route11} handler) + (ANY "/login" [] {:name :test/route23} handler) + (ANY "/orgs/:org-id/topics" [] {:name :test/route40} handler) + (ANY "/schemas" [] {:name :test/route44} handler) + (ANY "/topics/:topic" [] {:name :test/route47} handler) + (ANY "/topics" [] {:name :test/route50} handler)))) (def opensensors-pedestal-routes (map-tree/router @@ -509,8 +512,8 @@ (println route)))) (comment - (bench opensensors-routes false) - (bench opensensors-routes true)) + (bench opensensors-routes (fn [path] {:request-method :get, :uri path, :path-info path}) false) + (bench opensensors-routes (fn [path] {:request-method :get, :uri path, :path-info path}) true)) (comment @@ -540,12 +543,12 @@ (if-not match (println route))))) -(defn bench!! [routes verbose? name f] +(defn bench!! [routes req verbose? name f] (System/gc) (println) (suite name) (println) - (let [times (for [[path time] (bench-routes routes f)] + (let [times (for [[path time] (bench-routes routes req f)] (do (when verbose? (println (format "%7s" time) "\t" path)) time))] @@ -554,39 +557,39 @@ (defn bench-rest! [] (let [routes opensensors-routes router (reitit/router routes) - reitit-f #(reitit/match-by-path router %) - reitit-ring-f (let [app (ring/ring-handler (ring/router opensensors-routes))] - #(app {:uri % :request-method :get})) - bidi-f #(bidi/match-route opensensors-bidi-routes %) - ataraxy-f #(ataraxy/matches opensensors-ataraxy-routes {:uri %}) - compojure-f #(opensensors-compojure-routes {:uri % :request-method :get}) - compojure-api-f #(opensensors-compojure-api-routes {:uri % :request-method :get}) - pedestal-f #(pedestal/find-route opensensors-pedestal-routes {:path-info % :request-method :get})] + reitit-f #(reitit/match-by-path router (:uri %)) + reitit-ring-f (ring/ring-handler (ring/router opensensors-routes)) + bidi-f #(bidi/match-route opensensors-bidi-routes (:uri %)) + ataraxy-f (partial ataraxy/matches opensensors-ataraxy-routes) + compojure-f opensensors-compojure-routes + compojure-api-f opensensors-compojure-api-routes + pedestal-f (partial pedestal/find-route opensensors-pedestal-routes) + b! (partial bench!! routes (fn [path] {:request-method :get, :uri path, :path-info path}) true)] ;; 2538ns ;; 2065ns - ;; 680ns (prefix-tree-router) - (bench!! routes true "reitit" reitit-f) + ;; 662ns (prefix-tree-router) + (b! "reitit" reitit-f) ;; 2845ns ;; 2316ns - ;; 947ns (prefix-tree-router) - (bench!! routes true "reitit-ring" reitit-ring-f) + ;; 819ns (prefix-tree-router) + (b! "reitit-ring" reitit-ring-f) - ;; 2541ns - (bench!! routes true "pedestal" pedestal-f) + ;; 2540ns + (b! "pedestal" pedestal-f) - ;; 9462ns - (bench!! routes true "compojure-api" compojure-api-f) + ;; 10300ns + (b! "compojure-api" compojure-api-f) - ;; 11041ns - (bench!! routes true "compojure" compojure-f) + ;; 10800ns + (b! "compojure" compojure-f) - ;; 16820ns - (bench!! routes true "bidi" bidi-f) + ;; 15034ns + (b! "bidi" bidi-f) - ;; 24134ns - (bench!! routes true "ataraxy" ataraxy-f))) + ;; 19688ns + (b! "ataraxy" ataraxy-f))) (comment (bench-rest!)) @@ -595,9 +598,299 @@ ;; CQRSish ;; -(def commands #{:upsert-appeal :upsert-appeal-verdict :delete-appeal :delete-appeal-verdict :mark-seen :mark-everything-seen :upsert-application-handler :remove-application-handler :cancel-inforequest :cancel-application :cancel-application-authority :undo-cancellation :request-for-complement :cleanup-krysp :submit-application :refresh-ktj :save-application-drawings :create-application :add-operation :update-op-description :change-primary-operation :change-permit-sub-type :change-location :change-application-state :return-to-draft :change-warranty-start-date :change-warranty-end-date :add-link-permit :remove-link-permit-by-app-id :create-change-permit :create-continuation-period-permit :convert-to-application :add-bulletin-comment :move-to-proclaimed :move-to-verdict-given :move-to-final :save-proclaimed-bulletin :save-verdict-given-bulletin :set-municipality-hears-neighbors :archive-documents :mark-pre-verdict-phase-archived :save-asianhallinta-config :create-assignment :update-assignment :complete-assignment :bind-attachment :bind-attachments :set-attachment-type :approve-attachment :reject-attachment :reject-attachment-note :create-attachments :create-ram-attachment :delete-attachment :delete-attachment-version :upload-attachment :rotate-pdf :upsert-stamp-template :delete-stamp-template :stamp-attachments :sign-attachments :set-attachment-meta :set-attachment-not-needed :set-attachments-as-verdict-attachment :set-attachment-as-construction-time :set-attachment-visibility :convert-to-pdfa :invite-with-role :approve-invite :decline-invitation :remove-auth :change-auth :unsubscribe-notifications :subscribe-notifications :set-calendar-enabled-for-authority :create-calendar-slots :update-calendar-slot :delete-calendar-slot :add-reservation-type-for-organization :update-reservation-type :delete-reservation-type :reserve-calendar-slot :accept-reservation :decline-reservation :cancel-reservation :mark-reservation-update-seen :add-campaign :delete-campaign :change-email-init :change-email :can-target-comment-to-authority :can-mark-answered :add-comment :company-update :company-lock :company-user-update :company-user-delete :company-user-delete-all :company-invite-user :company-add-user :company-invite :company-cancel-invite :save-company-tags :update-application-company-notes :inform-construction-started :inform-construction-ready :copy-application :update-3d-map-server-details :set-3d-map-enabled :redirect-to-3d-map :create-archiving-project :submit-archiving-project :create-doc :remove-doc :set-doc-status :update-doc :update-task :remove-document-data :approve-doc :reject-doc :reject-doc-note :set-user-to-document :set-current-user-to-document :set-company-to-document :set-feature :remove-uploaded-file :create-foreman-application :update-foreman-other-applications :link-foreman-task :update-guest-authority-organization :remove-guest-authority-organization :invite-guest :toggle-guest-subscription :delete-guest-application :info-link-delete :info-link-reorder :info-link-upsert :mark-seen-organization-links :create-inspection-summary-template :delete-inspection-summary-template :modify-inspection-summary-template :set-inspection-summary-template-for-operation :create-inspection-summary :delete-inspection-summary :toggle-inspection-summary-locking :add-target-to-inspection-summary :edit-inspection-summary-target :remove-target-from-inspection-summary :set-target-status :set-inspection-date :approve-application :move-attachments-to-backing-system :parties-as-krysp :merge-details-from-krysp :application-to-asianhallinta :attachments-to-asianhallinta :order-verdict-attachment-prints :frontend-log :reset-frontend-log :new-verdict-template :set-verdict-template-name :save-verdict-template-draft-value :publish-verdict-template :toggle-delete-verdict-template :copy-verdict-template :save-verdict-template-settings-value :add-verdict-template-review :update-verdict-template-review :add-verdict-template-plan :update-verdict-template-plan :set-default-operation-verdict-template :upsert-phrase :delete-phrase :neighbor-add :neighbor-add-owners :neighbor-update :neighbor-remove :neighbor-send-invite :neighbor-mark-done :neighbor-response :change-urgency :add-authority-notice :add-application-tags :init-sign :cancel-sign :convert-to-normal-inforequests :update-organization :add-scope :create-organization :add-organization-link :update-organization-link :remove-organization-link :update-allowed-autologin-ips :set-organization-selected-operations :organization-operations-attachments :set-organization-app-required-fields-filling-obligatory :set-automatic-ok-for-attachments :set-organization-assignments :set-organization-inspection-summaries :set-organization-extended-construction-waste-report :set-organization-validate-verdict-given-date :set-organization-use-attachment-links-integration :set-organization-calendars-enabled :set-organization-boolean-attribute :set-organization-permanent-archive-start-date :set-organization-neighbor-order-email :set-organization-submit-notification-email :set-organization-inforequest-notification-email :set-organization-default-reservation-location :set-krysp-endpoint :set-kopiolaitos-info :save-vendor-backend-redirect-config :update-organization-name :save-organization-tags :update-map-server-details :update-user-layers :update-suti-server-details :section-toggle-enabled :section-toggle-operation :upsert-handler-role :toggle-handler-role :upsert-assignment-trigger :remove-assignment-trigger :update-docstore-info :browser-timing :create-application-from-previous-permit :screenmessages-add :screenmessages-reset :add-single-sign-on-key :update-single-sign-on-key :remove-single-sign-on-key :create-statement-giver :delete-statement-giver :request-for-statement :ely-statement-request :delete-statement :save-statement-as-draft :give-statement :request-for-statement-reply :save-statement-reply-as-draft :reply-statement :suti-toggle-enabled :suti-toggle-operation :suti-www :suti-update-id :suti-update-added :create-task :delete-task :approve-task :reject-task :review-done :mark-review-faulty :resend-review-to-backing-system :set-tos-function-for-operation :remove-tos-function-from-operation :set-tos-function-for-application :force-fix-tos-function-for-application :store-tos-metadata-for-attachment :store-tos-metadata-for-application :store-tos-metadata-for-process :set-myyntipalvelu-for-attachment :create-user :create-rest-api-user :update-user :applicant-to-authority :update-default-application-filter :save-application-filter :remove-application-filter :update-user-organization :remove-user-organization :update-user-roles :check-password :change-passwd :reset-password :admin-reset-password :set-user-enabled :login :impersonate-authority :register-user :confirm-account-link :retry-rakentajafi :remove-user-attachment :copy-user-attachments-to-application :remove-user-notification :notifications-update :check-for-verdict :new-verdict-draft :save-verdict-draft :publish-verdict :delete-verdict :sign-verdict :create-digging-permit}) - -(def queries #{:comments :actions :allowed-actions :allowed-actions-for-category :admin-attachment-report :appeals :application :application-authorities :application-commenters :enable-accordions :party-document-names :application-submittable :inforequest-markers :change-application-state-targets :link-permit-required :app-matches-for-link-permits :all-operations-in :application-handlers :application-organization-handler-roles :application-organization-archive-enabled :application-bulletins :application-bulletin-municipalities :application-bulletin-states :bulletin :bulletin-versions :bulletin-comments :publish-bulletin-enabled :municipality-hears-neighbors-visible :applications-search :applications-search-default :applications-for-new-appointment-page :get-application-operations :applications :latest-applications :event-search :tasks-tab-visible :application-info-tab-visible :application-summary-tab-visible :application-verdict-tab-visible :document-states :archiving-operations-enabled :permanent-archive-enabled :application-in-final-archiving-state :asianhallinta-config :assignments-for-application :assignment-targets :assignments-search :assignment-count :assignments :assignment :bind-attachments-job :attachments :attachment :attachment-groups :attachments-filters :attachments-tag-groups :attachment-types :ram-linked-attachments :attachment-operations :stamp-templates :custom-stamps :stamp-attachments-job :signing-possible :set-attachment-group-enabled :invites :my-calendars :calendar :calendars-for-authority-admin :calendar-slots :reservation-types-for-organization :available-calendar-slots :application-calendar-config :calendar-actions-required :applications-with-appointments :my-reserved-slots :campaigns :campaign :company :company-users-for-person-selector :company-tags :companies :user-company-locked :company-search-user :remove-company-tag-ok :company-notes :enable-company-search :info-construction-status :copy-application-invite-candidates :application-copyable-to-location :application-copyable :source-application :user-is-pure-digitizer :digitizing-enabled :document :validate-doc :fetch-validation-errors :schemas :features :apply-fixture :foreman-history :foreman-applications :resolve-guest-authority-candidate :guest-authorities-organization :application-guests :guest-authorities-application-organization :get-link-account-token :info-links :organization-links :organization-inspection-summary-settings :inspection-summaries-for-application :get-building-info-from-wfs :external-api-enabled :integration-messages :ely-statement-types :frontend-log-entries :newest-version :verdict-templates :verdict-template-categories :verdict-template :verdict-template-settings :verdict-template-reviews :verdict-template-plans :default-operation-verdict-templates :organization-phrases :application-phrases :owners :application-property-owners :municipality-borders :active-municipalities :municipality-active :neighbor-application :authority-notice :find-sign-process :organization-by-user :all-attachment-types-by-user :organization-name-by-user :user-organizations-for-permit-type :user-organizations-for-archiving-project :organizations :allowed-autologin-ips-for-organization :organization-by-id :permit-types :municipalities-with-organization :municipalities :all-operations-for-organization :selected-operations-for-municipality :addable-operations :organization-details :krysp-config :kopiolaitos-config :get-organization-names :vendor-backend-redirect-config :remove-tag-ok :get-organization-tags :get-organization-areas :get-map-layers-data :municipality-for-property :property-borders :screenmessages :get-single-sign-on-keys :get-organizations-statement-givers :get-possible-statement-statuses :get-statement-givers :statement-replies-enabled :statement-is-replyable :authorized-for-requesting-statement-reply :statement-attachment-allowed :statements-after-approve-allowed :neighbors-statement-enabled :suti-admin-details :suti-operations :suti-application-data :suti-application-products :suti-pre-sent-state :task-types-for-application :review-can-be-marked-done :is-end-review :available-tos-functions :tos-metadata-schema :case-file-data :tos-operations-enabled :common-area-application :user :users :users-in-same-organizations :user-by-email :users-for-datatables :saved-application-filters :redirect-after-login :user-attachments :add-user-attachment-allowed :email-in-use :enable-foreman-search :calendars-enabled :verdict-attachment-type :selected-digging-operations-for-organization :ya-extensions :approve-ya-extension}) +(def commands + #{:upsert-appeal + :upsert-appeal-verdict + :delete-appeal + :delete-appeal-verdict + :mark-seen + :mark-everything-seen + :upsert-application-handler + :remove-application-handler + :cancel-inforequest + :cancel-application + :cancel-application-authority + :undo-cancellation + :request-for-complement + :cleanup-krysp + :submit-application + :refresh-ktj + :save-application-drawings + :create-application + :add-operation + :update-op-description + :change-primary-operation + :change-permit-sub-type + :change-location + :change-application-state + :return-to-draft + :change-warranty-start-date + :change-warranty-end-date + :add-link-permit + :remove-link-permit-by-app-id + :create-change-permit + :create-continuation-period-permit + :convert-to-application + :add-bulletin-comment + :move-to-proclaimed + :move-to-verdict-given + :move-to-final + :save-proclaimed-bulletin + :save-verdict-given-bulletin + :set-municipality-hears-neighbors + :archive-documents + :mark-pre-verdict-phase-archived + :save-asianhallinta-config + :create-assignment + :update-assignment + :complete-assignment + :bind-attachment + :bind-attachments + :set-attachment-type + :approve-attachment + :reject-attachment + :reject-attachment-note + :create-attachments + :create-ram-attachment + :delete-attachment + :delete-attachment-version + :upload-attachment + :rotate-pdf + :upsert-stamp-template + :delete-stamp-template + :stamp-attachments + :sign-attachments + :set-attachment-meta + :set-attachment-not-needed + :set-attachments-as-verdict-attachment + :set-attachment-as-construction-time + :set-attachment-visibility + :convert-to-pdfa + :invite-with-role + :approve-invite + :decline-invitation + :remove-auth + :change-auth + :unsubscribe-notifications + :subscribe-notifications + :set-calendar-enabled-for-authority + :create-calendar-slots + :update-calendar-slot + :delete-calendar-slot + :add-reservation-type-for-organization + :update-reservation-type + :delete-reservation-type + :reserve-calendar-slot + :accept-reservation + :decline-reservation + :cancel-reservation + :mark-reservation-update-seen + :add-campaign + :delete-campaign + :change-email-init + :change-email + :can-target-comment-to-authority + :can-mark-answered + :add-comment + :company-update + :company-lock + :company-user-update + :company-user-delete + :company-user-delete-all + :company-invite-user + :company-add-user + :company-invite + :company-cancel-invite + :save-company-tags + :update-application-company-notes + :inform-construction-started + :inform-construction-ready + :copy-application + :update-3d-map-server-details + :set-3d-map-enabled + :redirect-to-3d-map + :create-archiving-project + :submit-archiving-project + :create-doc + :remove-doc + :set-doc-status + :update-doc + :update-task + :remove-document-data + :approve-doc + :reject-doc + :reject-doc-note + :set-user-to-document + :set-current-user-to-document + :set-company-to-document + :set-feature + :remove-uploaded-file + :create-foreman-application + :update-foreman-other-applications + :link-foreman-task + :update-guest-authority-organization + :remove-guest-authority-organization + :invite-guest + :toggle-guest-subscription + :delete-guest-application + :info-link-delete + :info-link-reorder + :info-link-upsert + :mark-seen-organization-links + :create-inspection-summary-template + :delete-inspection-summary-template + :modify-inspection-summary-template + :set-inspection-summary-template-for-operation + :create-inspection-summary + :delete-inspection-summary + :toggle-inspection-summary-locking + :add-target-to-inspection-summary + :edit-inspection-summary-target + :remove-target-from-inspection-summary + :set-target-status + :set-inspection-date + :approve-application + :move-attachments-to-backing-system + :parties-as-krysp + :merge-details-from-krysp + :application-to-asianhallinta + :attachments-to-asianhallinta + :order-verdict-attachment-prints + :frontend-log + :reset-frontend-log + :new-verdict-template + :set-verdict-template-name + :save-verdict-template-draft-value + :publish-verdict-template + :toggle-delete-verdict-template + :copy-verdict-template + :save-verdict-template-settings-value + :add-verdict-template-review + :update-verdict-template-review + :add-verdict-template-plan + :update-verdict-template-plan + :set-default-operation-verdict-template + :upsert-phrase + :delete-phrase + :neighbor-add + :neighbor-add-owners + :neighbor-update + :neighbor-remove + :neighbor-send-invite + :neighbor-mark-done + :neighbor-response + :change-urgency + :add-authority-notice + :add-application-tags + :init-sign + :cancel-sign + :convert-to-normal-inforequests + :update-organization + :add-scope + :create-organization + :add-organization-link + :update-organization-link + :remove-organization-link + :update-allowed-autologin-ips + :set-organization-selected-operations + :organization-operations-attachments + :set-organization-app-required-fields-filling-obligatory + :set-automatic-ok-for-attachments + :set-organization-assignments + :set-organization-inspection-summaries + :set-organization-extended-construction-waste-report + :set-organization-validate-verdict-given-date + :set-organization-use-attachment-links-integration + :set-organization-calendars-enabled + :set-organization-boolean-attribute + :set-organization-permanent-archive-start-date + :set-organization-neighbor-order-email + :set-organization-submit-notification-email + :set-organization-inforequest-notification-email + :set-organization-default-reservation-location + :set-krysp-endpoint + :set-kopiolaitos-info + :save-vendor-backend-redirect-config + :update-organization-name + :save-organization-tags + :update-map-server-details + :update-user-layers + :update-suti-server-details + :section-toggle-enabled + :section-toggle-operation + :upsert-handler-role + :toggle-handler-role + :upsert-assignment-trigger + :remove-assignment-trigger + :update-docstore-info + :browser-timing + :create-application-from-previous-permit + :screenmessages-add + :screenmessages-reset + :add-single-sign-on-key + :update-single-sign-on-key + :remove-single-sign-on-key + :create-statement-giver + :delete-statement-giver + :request-for-statement + :ely-statement-request + :delete-statement + :save-statement-as-draft + :give-statement + :request-for-statement-reply + :save-statement-reply-as-draft + :reply-statement + :suti-toggle-enabled + :suti-toggle-operation + :suti-www + :suti-update-id + :suti-update-added + :create-task + :delete-task + :approve-task + :reject-task + :review-done + :mark-review-faulty + :resend-review-to-backing-system + :set-tos-function-for-operation + :remove-tos-function-from-operation + :set-tos-function-for-application + :force-fix-tos-function-for-application + :store-tos-metadata-for-attachment + :store-tos-metadata-for-application + :store-tos-metadata-for-process + :set-myyntipalvelu-for-attachment + :create-user + :create-rest-api-user + :update-user + :applicant-to-authority + :update-default-application-filter + :save-application-filter + :remove-application-filter + :update-user-organization + :remove-user-organization + :update-user-roles + :check-password + :change-passwd + :reset-password + :admin-reset-password + :set-user-enabled + :login + :impersonate-authority + :register-user + :confirm-account-link + :retry-rakentajafi + :remove-user-attachment + :copy-user-attachments-to-application + :remove-user-notification + :notifications-update + :check-for-verdict + :new-verdict-draft + :save-verdict-draft + :publish-verdict + :delete-verdict + :sign-verdict + :create-digging-permit}) (def cqrs-routes (mapv (fn [command] [(str "/command/" (name command)) {:post handler :name command}]) commands)) @@ -607,9 +900,16 @@ (table/table-routes (mapv (fn [command] [(str "/command/" (name command)) :post handler :route-name command]) commands)))) -(class (:tree-map cqrs-routes-pedestal)) +(def cqrs-routes-bidi + ["/command/" (into {} (mapv (fn [command] [(name command) command]) commands))]) -(class (:data (ring/router cqrs-routes))) +(def cqrs-routes-compojure + (apply routes (map (fn [command] (compojure/ANY (str "/command/" (name command)) [] handler)) commands))) + +;; Method code too large +#_(def cqrs-routes-ataraxy + (ataraxy/compile + (into {} (mapv (fn [command] [(str "/command/" (name command)) [command]]) commands)))) (comment @@ -627,22 +927,32 @@ (defn bench-cqrs! [] (let [routes cqrs-routes router (reitit/router cqrs-routes) - reitit-f #(reitit/match-by-path router %) - reitit-ring-f (let [app (ring/ring-handler (ring/router routes))] - #(app {:uri % :request-method :post})) - pedestal-f #(pedestal/find-route cqrs-routes-pedestal {:path-info % :request-method :post})] + reitit-f #(reitit/match-by-path router (:uri %)) + reitit-ring-f (ring/ring-handler (ring/router routes)) + pedestal-f (partial pedestal/find-route cqrs-routes-pedestal) + compojure-f cqrs-routes-compojure + bidi-f #(bidi/match-route cqrs-routes-bidi (:uri %)) + b! (partial bench!! routes (fn [path] {:request-method :post, :uri path, :path-info path}) false)] ;; 125ns - ;; 62ns (fast-map) - (bench!! routes false "reitit" reitit-f) + ;; 29ns (fast-map) + (b! "reitit" reitit-f) ;; 272ns ;; 219ns (fast-assoc) ;; 171ns (fast-map) - (bench!! routes false "reitit-ring" reitit-ring-f) + ;; 95ns (refined test, don't check handler) + (b! "reitit-ring" reitit-ring-f) ;; 172ns - (bench!! routes false "pedestal" pedestal-f))) + ;; 133ns (refined test) + (b! "pedestal" pedestal-f) + + ;; 21972ns (refined test) + (b! "compojure" compojure-f) + + ;; 62762ns (refined test) + (b! "bidi" bidi-f))) (comment (bench-cqrs!)) diff --git a/project.clj b/project.clj index 0141a2bf..0155895a 100644 --- a/project.clj +++ b/project.clj @@ -32,7 +32,7 @@ "modules/reitit-ring/src" "modules/reitit-spec/src"] - :dependencies [[org.clojure/clojure "1.9.0-beta4"] + :dependencies [[org.clojure/clojure "1.9.0-RC1"] [org.clojure/clojurescript "1.9.946"] ;; all modules dependencies