A Clojure library to manage database migrations for Datomic
Transmutations are versioned transactions that are committed to the database in order. As Alchemist commits the transaction it is annotated with :alchemist/version, :alchemist/description, and :alchemist/hash attributes. When Alchemist is run again it will not re-commit the transactions below the current state.
Create properly named edn files into the transmutations directory:
MyProject
resources/
transmutations/
v1_0_0__initial_commit.edn
v1_1_0__more_schema.edn
containing transaction data:
[{:db/id #db/id[:db.part/db]
:db/ident :sample/attribute
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :sample/attribute2
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}
]
and run with the defaults:
(require '[alchemist])
(alchemist/transmute "datomic:mem://testdb")
alchemist keeps track of which transmutations have already run by annotating the transactions
{:alchemist/version "1.0.0"
:alchemist/description "initial_commit"
:alchemist/hash 236679938}
and will not transact them a second time so feel free to run at app start-up every time.
transmyo͞oˈtāSHn
noun
- the action of changing or the state of being changed into another form
- a function, wrapped in a map, that produces a Datomic transaction vector
{:alchemist/version "1.0.0a"
:alchemist/description "initial_schema"
:dynamic? true
:transaction-fn my-transaction-producing-function}
:alchemist/version A string containing "." separated elements. Each element will be compared independently from left to right. Versions will be transacted in ascending order.
:alchemist/description A description that will be annotated on the transaction.
:dynamic? If true then the transaction vector's hash will not be compared during verification. If false and the transaction vector's hash changes between runs then verification will fail.
Note: the #db/id reader macro produces variable results so the :db/id keys will be replaced with relative values prior to getting the hash so that the numbers are consistent.
:transaction-fn If alchemist produces the transmutation through classpath scanning the function will read the file lazily. Any function that produces transaction edn is valid.
{:create? true
:verify? true
:update? true
:scan? true
:parent-directories ["transmutations"]
:cp-excludes [#".*/?jre/\S*.jar"
#".*/?clojure\S*.jar"
#".*/?datomic\S*.jar"
#".*/?bin"]}
:create? boolean, allows for creation of a database if it is not found at the provided uri
:verify? boolean, will cause an exception to be thrown if the transmutations up to the current version of the database do not match those found in database
:update? boolean, allows previously not run transmutations to be committed
:scan? boolean, enables classpath scanning to discover transmutation files
:parent-directories a vector of parent directory names to scan for transmutations
:cp-excludes a vector of regexes to filter the classpath prior to scanning
(require '[alchemist :as a])
(a/transmute "datomic:mem://testdb"
(merge a/default-config
{:create? false
:parent-directories ["transmutations" "sample_data"]}))
File Naming Rules
- start with the letter "v" (case doesn't matter)
- followed by dot "." or under-bar "_" separated version segments (under-bars will be translated into dots at runtime)
- followed by a double under-bar "__"
- followed by a description string
- ending with a ".edn" or ".clj" extension
Copyright © 2013 Dylan Bijnagte
Distributed under the Eclipse Public License, the same as Clojure.