|
| 1 | +(ns reitit-db-fun.core |
| 2 | + (:require [clojure.java.io :as io] |
| 3 | + [integrant.core :as ig] |
| 4 | + [aleph.http :as http] |
| 5 | + [reitit.ring :as ring] |
| 6 | + [muuntaja.core :as m] |
| 7 | + [reitit.ring.middleware.muuntaja :as muuntaja] |
| 8 | + [reitit.coercion.malli] |
| 9 | + [reitit.coercion :as coercion] |
| 10 | + [clojure.tools.logging :as log] |
| 11 | + |
| 12 | + [reitit-db-fun.model] |
| 13 | + [reitit-db-fun.model-impl] |
| 14 | + [reitit-db-fun.storage] |
| 15 | + ;; XTDB |
| 16 | + [xtdb.api :as xt] |
| 17 | + |
| 18 | + ;; Datalevin |
| 19 | + [datalevin.core :as d] |
| 20 | + |
| 21 | + ;; JDBC |
| 22 | + [next.jdbc :as jdbc] |
| 23 | + [next.jdbc.sql :as jdbc-sql] |
| 24 | + [honey.sql :as sql] |
| 25 | + [honey.sql.helpers :as h] |
| 26 | + |
| 27 | + ;; Datoms |
| 28 | + [reitit-db-fun.datom :as datom])) |
| 29 | + |
| 30 | +;; ==== Config ==== |
| 31 | + |
| 32 | +(def config {:app/handler {:keys-to-wrap |
| 33 | + {#_#_:node (ig/ref :storage/xtdb) |
| 34 | + :model (ig/ref #_:model/article-datalevin |
| 35 | + :model/article-sql |
| 36 | + #_:model/article-xtdb)}} |
| 37 | + |
| 38 | + :model/article-xtdb {:node (ig/ref :storage/xtdb)} |
| 39 | + :model/article-datalevin {:conn (ig/ref :storage/datalevin)} |
| 40 | + :model/article-sql {:datasource (ig/ref :storage/sql)} |
| 41 | + |
| 42 | + :adapter/aleph {:port 8080 |
| 43 | + :handler (ig/ref :app/handler)} |
| 44 | + |
| 45 | + :storage/xtdb {} |
| 46 | + :storage/datalevin {:uri "datalevin.db" |
| 47 | + :schema {}} |
| 48 | + :storage/sql {:conn-options {:jdbc-url "jdbc:sqlite:database.sqlite"} |
| 49 | + :migrations-dir "migrations"}}) |
| 50 | + |
| 51 | + |
| 52 | +(defn wrap-keys |
| 53 | + [keys-to-wrap] |
| 54 | + (fn [handler] |
| 55 | + (fn [request] |
| 56 | + (handler (merge request keys-to-wrap))))) |
| 57 | + |
| 58 | +(defn get-article-handler |
| 59 | + [{:keys [model path-params]}] |
| 60 | + (println "DEBUG:" (pr-str path-params)) |
| 61 | + ;; TODO proper coercion |
| 62 | + {:body (reitit-db-fun.model/get-article model (:article-id path-params))}) |
| 63 | + |
| 64 | +(defn get-articles-handler [{:keys [model]}] |
| 65 | + {:body (reitit-db-fun.model/get-articles model)}) |
| 66 | + |
| 67 | +(defn update-article-handler [{:keys [model body-params]}] |
| 68 | + {:body (reitit-db-fun.model/update-article model body-params)}) |
| 69 | + |
| 70 | + |
| 71 | +(defn get-app-handler [{:keys [keys-to-wrap]}] |
| 72 | + (ring/ring-handler |
| 73 | + (ring/router |
| 74 | + ["/api" |
| 75 | + ["/articles" |
| 76 | + {:get get-articles-handler}] |
| 77 | + ["/article" |
| 78 | + {:post update-article-handler}] |
| 79 | + ["/article/:article-id" |
| 80 | + {:get get-article-handler}] |
| 81 | + ["/ping" |
| 82 | + {:get {:handler (fn [req] |
| 83 | + {:status 200 |
| 84 | + :body {:message "pong" |
| 85 | + :request (pr-str req)}})}}] |
| 86 | + ["/status" |
| 87 | + {:get {:handler (fn [req] |
| 88 | + {:status 200 |
| 89 | + :body {:message "status" |
| 90 | + :model (pr-str (:model req))}})}}]] |
| 91 | + ;; router data affecting all routes |
| 92 | + {:data {:muuntaja m/instance |
| 93 | + :middleware [muuntaja/format-middleware |
| 94 | + muuntaja/format-response-middleware |
| 95 | + (wrap-keys keys-to-wrap)]}}))) |
| 96 | + |
| 97 | +(defonce main-system (atom nil)) |
| 98 | + |
| 99 | +(defmethod ig/init-key :adapter/aleph [_ {:keys [handler port]}] |
| 100 | + (http/start-server handler {:port port})) |
| 101 | + |
| 102 | +(defmethod ig/halt-key! :adapter/aleph [_ server] |
| 103 | + (.close server)) |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | +(defmethod ig/init-key :app/handler [_ {:keys [keys-to-wrap]}] |
| 108 | + (get-app-handler {:keys-to-wrap keys-to-wrap})) |
| 109 | + |
| 110 | +(defn start-system [system-atom config] |
| 111 | + (log/info "Starting system") |
| 112 | + (let [system @system-atom] |
| 113 | + (when-not system |
| 114 | + (ig/load-namespaces config) |
| 115 | + (reset! system-atom (ig/init config))))) |
| 116 | + |
| 117 | +(defn stop-system [system-atom] |
| 118 | + (log/info "Stopping system") |
| 119 | + (let [system @system-atom] |
| 120 | + (when system |
| 121 | + (reset! system-atom (ig/halt! system))))) |
| 122 | + |
| 123 | +(defn -main [_] |
| 124 | + (start-system main-system config)) |
| 125 | + |
| 126 | + |
| 127 | +(defn restart-system [] |
| 128 | + (stop-system main-system) |
| 129 | + (start-system main-system config)) |
| 130 | + |
| 131 | + |
| 132 | +(comment |
| 133 | + (restart-system) |
| 134 | + |
| 135 | + |
| 136 | + (-> ((:app/handler @main-system) |
| 137 | + {:request-method :post |
| 138 | + :uri "/api/article" |
| 139 | + :body-params {#_#_:xt/id 1 |
| 140 | + :article/id "3ba51497-4a08-4e48-9b2c-ec4c88930da7" |
| 141 | + :article/title "Title zmieniony ponownie" |
| 142 | + :article/author "pkoza" |
| 143 | + :article/gerne "blog"}}) |
| 144 | + :body |
| 145 | + slurp |
| 146 | + ) |
| 147 | + |
| 148 | + (-> ((:app/handler @main-system) |
| 149 | + {:request-method :get |
| 150 | + :uri "/api/article/1"}) |
| 151 | + :body |
| 152 | + slurp) |
| 153 | + |
| 154 | + (-> ((:app/handler @main-system) |
| 155 | + {:request-method :get |
| 156 | + :uri "/api/articles"}) |
| 157 | + :body |
| 158 | + slurp) |
| 159 | + |
| 160 | + |
| 161 | + (let [app (:app/handler @main-system)] |
| 162 | + (doseq [idx (range 1000)] |
| 163 | + (app {:request-method :post |
| 164 | + :uri "/api/article" |
| 165 | + :body-params {:article/title (str "Test-" (inc idx)) |
| 166 | + :article/author "pkoza" |
| 167 | + #_#_:article/id idx}}))) |
| 168 | + |
| 169 | + (let [node (:storage/xtdb @main-system) |
| 170 | + id 1] |
| 171 | + (xt/q (xt/db node) |
| 172 | + '{:find [(pull ?e [*])] |
| 173 | + :in [id] |
| 174 | + :where [[?e :xt/id id]]} |
| 175 | + id)) |
| 176 | + |
| 177 | + (-> (:model/article-datalevin @main-system) |
| 178 | + (reitit-db-fun.model/get-articles {})) |
| 179 | + |
| 180 | + |
| 181 | + ;; Datalevin test |
| 182 | + |
| 183 | + (let [conn (:storage/datalevin @main-system)] |
| 184 | + (d/transact! conn |
| 185 | + [{:article/title "A Frege", :db/id -1, :article/nation "France", :article/aka ["foo" "fred"]} |
| 186 | + {:article/title "A Peirce", :db/id -2, :article/nation "france"} |
| 187 | + {:article/title "De Morgan", :db/id -3, :article/nation "English"}])) |
| 188 | + |
| 189 | + (let [conn (:storage/datalevin @main-system)] |
| 190 | + (d/q '[:find ?nation |
| 191 | + :in $ ?alias |
| 192 | + :where |
| 193 | + [?e :article/aka ?alias] |
| 194 | + [?e :article/nation ?nation]] |
| 195 | + (d/db conn) |
| 196 | + "foo")) |
| 197 | + |
| 198 | + (let [conn (:storage/datalevin @main-system)] |
| 199 | + (d/q '[:find (pull ?e [*]) |
| 200 | + :where |
| 201 | + [?e :article/title]] |
| 202 | + (d/db conn))) |
| 203 | + (let [conn (:storage/datalevin @main-system)] |
| 204 | + (d/q '[:find (pull ?article-id [*]) |
| 205 | + :in $ ?article-id |
| 206 | + :where |
| 207 | + [?e :db/id ?article-id]] |
| 208 | + (d/db conn) |
| 209 | + 18)) |
| 210 | + ;; jdbc |
| 211 | + |
| 212 | + |
| 213 | + (-> |
| 214 | + (let [datasource (:storage/sql @main-system) |
| 215 | + {:article/keys [id title author]} {:article/id "9898906f-ce7f-42ad-a66d-7173b2c2bd03" |
| 216 | + :article/title "Tytuł zmieniony" |
| 217 | + :article/author "tester!"} |
| 218 | + |
| 219 | + result (if id |
| 220 | + (jdbc-sql/update! datasource :articles |
| 221 | + {:title title :author author} |
| 222 | + {:id id}) |
| 223 | + (jdbc-sql/insert! datasource :articles |
| 224 | + {:id (str (java.util.UUID/randomUUID)) |
| 225 | + :title title |
| 226 | + :author author}))] |
| 227 | + (if id |
| 228 | + (jdbc-sql/query datasource ["select * from articles where id = ?" id]) |
| 229 | + (jdbc-sql/query datasource ["select * from articles where rowid = ?" |
| 230 | + ((keyword "last_insert_rowid()")) result])))) |
| 231 | + |
| 232 | + (time (count (let [datasource (:storage/sql @main-system) |
| 233 | + query (sql/format {:select :* |
| 234 | + :from :article |
| 235 | + #_#_:limit 10})] |
| 236 | + (->> (jdbc/execute! datasource query) |
| 237 | + (into #{} (mapcat datom/entity->datoms)))))) |
| 238 | + |
| 239 | + ) |
0 commit comments