83 lines
4.0 KiB
Clojure
83 lines
4.0 KiB
Clojure
(ns beherbergung.db.state
|
|
(:require[xtdb.api :as xtdb]
|
|
[clojure.java.io :as io]
|
|
[beherbergung.db.export :refer [export seed ]]
|
|
[mount.core :as mount :refer [defstate]]
|
|
[beherbergung.config.state :refer [env]]
|
|
[beherbergung.db.validate :refer [validate-db validate-tx]]))
|
|
|
|
(defn export-named-by-date [db_ctx cause]
|
|
(when (:db-export-prefix env)
|
|
(let [date (.format (java.text.SimpleDateFormat. "yyyy-MM-dd_HH:mm:ss")
|
|
(.getTime (java.util.Calendar/getInstance)))
|
|
file (str (:db-export-prefix env) date "_" cause ".edn")]
|
|
(when (:verbose env)
|
|
(println "Export database to:" file))
|
|
(io/make-parents file)
|
|
(export file db_ctx))))
|
|
|
|
(defn submit-tx [node tx-ops]
|
|
(xtdb/submit-tx node (validate-tx tx-ops)))
|
|
|
|
(defn q [node & args]
|
|
(apply xtdb/q (xtdb/db node) args))
|
|
|
|
(defn ->db_ctx []
|
|
(let [node (xtdb/start-node (when-not (:db-inmemory env)
|
|
{:my-rocksdb {:xtdb/module 'xtdb.rocksdb/->kv-store
|
|
:db-dir (clojure.java.io/file (:db-dir env))
|
|
:sync? true}
|
|
:xtdb/tx-log {:kv-store :my-rocksdb}
|
|
:xtdb/document-store {:kv-store :my-rocksdb}})) ;; To optimize for read performance, we might switch to LMDB (B-Tree instead of LSM-Tree)
|
|
;; But for our workload it doesn't matter much
|
|
db_ctx {:node node
|
|
:tx (fn [tx-ops]
|
|
(submit-tx node tx-ops))
|
|
:tx_sync (fn [tx-ops]
|
|
(->> (submit-tx node tx-ops)
|
|
(xtdb.api/await-tx node)))
|
|
:tx-committed? (fn [transaction]
|
|
#_(println "synced" (xtdb/sync node))
|
|
#_(println "awaited" (xtdb/await-tx node transaction))
|
|
(xtdb/tx-committed? node transaction))
|
|
:tx-fn-put (fn [fn-name quoted-fn]
|
|
;; In future we may want add transaction functions only once (at startup)
|
|
(xtdb/submit-tx node [[::xtdb/put {:xt/id fn-name :xt/fn quoted-fn}]]))
|
|
:tx-fn-call (fn [fn-name & args]
|
|
(xtdb/submit-tx node [(concat [::xtdb/fn fn-name] args)]))
|
|
:sync (fn [] (xtdb/sync node))
|
|
:q (fn [& args]
|
|
(apply q node args))
|
|
:q_unary (fn [& args]
|
|
;; A query returning unary results
|
|
(->> (apply q node args)
|
|
(map first)))
|
|
:q_id (fn [& args]
|
|
;; A query returning only 1 result
|
|
(-> (apply q node args)
|
|
first))
|
|
:q_id_unary (fn [& args]
|
|
;; A query returning only 1 unary result
|
|
(-> (apply q node args)
|
|
ffirst))}]
|
|
|
|
(export-named-by-date db_ctx "start") ;; before seeding
|
|
|
|
;; There is no default seed file, to prevent loading it into the production system
|
|
(if (:db-seed env)
|
|
(do (when (:verbose env)
|
|
(println "Seed the database from:" (:db-seed env)))
|
|
(seed (:db-seed env) db_ctx))
|
|
(println "WARNING: Seeding the database requires setting $DB_SEED"
|
|
"consider: DB_SEED=src/beherbergung/db/seed/test.edn"))
|
|
|
|
(if (:db-validate env)
|
|
(or (validate-db db_ctx)
|
|
(System/exit 1))
|
|
db_ctx)))
|
|
|
|
(defstate db_ctx
|
|
:start (->db_ctx)
|
|
:stop (do (export-named-by-date db_ctx "stop")
|
|
(.close (:node db_ctx))))
|