Skip to content

Commit

Permalink
Add MigrationIndex protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
weavejester committed Dec 3, 2024
1 parent 0641a20 commit 0bf4838
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 12 deletions.
38 changes: 27 additions & 11 deletions core/src/ragtime/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,27 @@
[ragtime.strategy :as strategy]
[ragtime.reporter :as reporter]))

(extend-protocol p/MigrationIndex
clojure.lang.IPersistentMap
(index-migration [index key migration]
(assoc index key migration))
(deindex-migration [index key]
(dissoc index key))
(get-indexed-migration [index key not-found]
(get index key not-found)))

(defn into-index
"Add migrations to a map, using their :id as the key."
"Add migrations to a map, using their ID as the key."
([migrations]
(into-index {} migrations))
([index migrations]
(into index (map (juxt p/id identity) migrations))))
(reduce #(p/index-migration %1 (p/id %2) %2) index migrations)))

(defn applied-migrations
"List all migrations in the index that are applied to the database."
[store index]
(->> (p/applied-migration-ids store)
(map index)
(remove nil?)))
(keep #(p/get-indexed-migration index % nil)
(p/applied-migration-ids store)))

(defn migrate
"Apply a single migration to a data store."
Expand Down Expand Up @@ -60,10 +68,17 @@
(throw (InterruptedException.
(str "Stopping running migrations before " migration-id
" because the current thread has been interrupted"))))
(reporter store ({:migrate :up, :rollback :down} action) migration-id)
(case action
:migrate (migrate store (index migration-id))
:rollback (rollback store (index migration-id)))))))
(if-some [migration (p/get-indexed-migration index migration-id nil)]
(case action
:migrate (do (reporter store :up migration-id)
(migrate store migration))
:rollback (do (reporter store :down migration-id)
(rollback store migration)))
(throw (ex-info (str "Could not find migration '" migration-id
"' in index")
{:reason ::migration-not-indexed
:index index
:migration-id migration-id})))))))

(defn rollback-last
"Rollback the last n migrations from the database, using the supplied
Expand Down Expand Up @@ -93,8 +108,9 @@
discards (->> (reverse migrations)
(take-while #(not= (p/id %) migration-id)))]
(if (= (count discards) (count migrations))
(throw (ex-info (str "Could not find migration '" migration-id "' in data store")
{:reason ::migration-not-found
(throw (ex-info (str "Could not find migration '" migration-id
"' in data store")
{:reason ::migration-not-stored
:store store
:migration-id migration-id}))
(doseq [migration discards]
Expand Down
12 changes: 11 additions & 1 deletion core/src/ragtime/protocols.clj
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,14 @@
(remove-migration-id [store migration-id]
"Remove a rolled-back migration ID from the data store.")
(applied-migration-ids [store]
"Return an ordered list of ids of all migrations applied to the data store."))
"Return an ordered list of ids of all migrations applied to the data
store."))

(defprotocol MigrationIndex
"Protocol for keeping an index of migrations."
(index-migration [index key migration]
"Add a migration to the index with the supplied key.")
(deindex-migration [index key]
"Remove a migration from the index.")
(get-indexed-migration [index key not-found]
"Get a migration from the index."))
15 changes: 15 additions & 0 deletions core/test/ragtime/core_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@
(is (= (index "assoc-x") assoc-x))
(is (= ((ragtime/into-index index [assoc-y]) "assoc-y") assoc-y))))

(deftest test-custom-indeex
(let [index-db (atom {})
index (reify p/MigrationIndex
(index-migration [index id migration]
(swap! index-db assoc id migration) index)
(deindex-migration [index id]
(swap! index-db dissoc id) index)
(get-indexed-migration [_ id not-found]
(@index-db id not-found)))
assoc-x (assoc-migration "assoc-x" :x 1)
assoc-y (assoc-migration "assoc-y" :y 2)
index' (ragtime/into-index index [assoc-x assoc-y])]
(is (= assoc-x (p/get-indexed-migration index' "assoc-x" nil)))
(is (= assoc-y (p/get-indexed-migration index' "assoc-y" nil)))))

(deftest test-migrate-and-rollback
(let [database (in-memory-db)
migration (assoc-migration "m" :x 1)
Expand Down

0 comments on commit 0bf4838

Please sign in to comment.