Skip to content

Instantly share code, notes, and snippets.

@kordano
Created November 26, 2022 11:50
Show Gist options
  • Save kordano/1cddb8c485dc18d1c48d275631c53301 to your computer and use it in GitHub Desktop.
Save kordano/1cddb8c485dc18d1c48d275631c53301 to your computer and use it in GitHub Desktop.
Datahike schema migration idea
{:norm :a1-example
:tx-data [{:db/doc "example"
:db/ident :example
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one}]
:tx-fn io.replikativ.garantie/neutral-fn}
(ns datahike.norm
(:require
[clojure.java.io :as io]
[taoensso.timbre :as log]
[clojure.string :as string]
[datahike.api :as d]))
(defn attribute-installed? [conn attr]
(some? (d/entity @conn [:db/ident attr])))
(defn ensure-norm-attribute! [conn]
(if-not (attribute-installed? conn :tx/norm)
(:db-after (d/transact conn {:tx-data [{:db/ident :tx/norm
:db/valueType :db.type/keyword
:db/cardinality :db.cardinality/one}]}))
@conn))
(defn norm-installed? [db norm]
(->> {:query '[:find (count ?t)
:in $ ?tn
:where
[_ :tx/norm ?tn ?t]]
:args [db norm]}
d/q
first
some?))
(defn read-norm-files! [norms-folder]
(let [folder (io/file norms-folder)]
(if (.exists folder)
(let [
migration-files (file-seq folder)
xf (comp
(filter #(re-find #".edn" (.getPath %)))
(map (fn [migration-file]
(-> (.getPath migration-file)
slurp
read-string
(update :norm (fn [norm] (or norm
(-> (.getName migration-file)
(string/replace #"\.edn" "")
keyword))))))))]
(sort-by :norm (into [] xf migration-files)))
(throw
(ex-info
(format "Norms folder %s does not exist." norms-folder)
{:folder norms-folder})))))
(defn neutral-fn [_] [])
(defn ensure-norms!
([conn]
(ensure-norms! conn (io/resource "migrations")))
([conn migrations-folder]
(let [db (ensure-norm-attribute! conn)
norm-list (read-norm-files! migrations-folder)]
(log/info "Checking migrations ...")
(doseq [{:keys [norm tx-data tx-fn]
:or {tx-data []
tx-fn #'neutral-fn}} norm-list]
(log/info "Checking migration" norm)
(when-not (norm-installed? db norm)
(log/info "Run migration" norm)
(d/transact conn {:tx-data (vec (concat [{:tx/norm norm}]
tx-data
(tx-fn conn)))})))
(log/info "Done"))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment