mirror of
https://github.com/penpot/penpot.git
synced 2025-05-18 12:56:11 +02:00
86 lines
2.6 KiB
Clojure
86 lines
2.6 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
|
;; defined by the Mozilla Public License, v. 2.0.
|
|
;;
|
|
;; Copyright (c) 2020 UXBOX Labs SL
|
|
|
|
(ns app.util.migrations
|
|
(:require
|
|
[clojure.java.io :as io]
|
|
[clojure.spec.alpha :as s]
|
|
[clojure.tools.logging :as log]
|
|
[cuerdas.core :as str]
|
|
[next.jdbc :as jdbc]))
|
|
|
|
(s/def ::name string?)
|
|
(s/def ::step (s/keys :req-un [::name ::fn]))
|
|
(s/def ::steps (s/every ::step :kind vector?))
|
|
(s/def ::migrations
|
|
(s/keys :req-un [::name ::steps]))
|
|
|
|
;; --- Implementation
|
|
|
|
(defn- registered?
|
|
"Check if concrete migration is already registred."
|
|
[pool modname stepname]
|
|
(let [sql "select * from migrations where module=? and step=?"
|
|
rows (jdbc/execute! pool [sql modname stepname])]
|
|
(pos? (count rows))))
|
|
|
|
(defn- register!
|
|
"Register a concrete migration into local migrations database."
|
|
[pool modname stepname]
|
|
(let [sql "insert into migrations (module, step) values (?, ?)"]
|
|
(jdbc/execute! pool [sql modname stepname])
|
|
nil))
|
|
|
|
(defn- impl-migrate-single
|
|
[pool modname {:keys [name] :as migration}]
|
|
(when-not (registered? pool modname (:name migration))
|
|
(log/info (str/format "applying migration %s/%s" modname name))
|
|
(register! pool modname name)
|
|
((:fn migration) pool)))
|
|
|
|
(defn- impl-migrate
|
|
[conn migrations _opts]
|
|
(s/assert ::migrations migrations)
|
|
(let [mname (:name migrations)
|
|
steps (:steps migrations)]
|
|
(jdbc/with-transaction [conn conn]
|
|
(run! #(impl-migrate-single conn mname %) steps))))
|
|
|
|
(defprotocol IMigrationContext
|
|
(-migrate [_ migration options]))
|
|
|
|
;; --- Public Api
|
|
(defn setup!
|
|
"Initialize the database if it is not initialized."
|
|
[conn]
|
|
(let [sql (str "create table if not exists migrations ("
|
|
" module text,"
|
|
" step text,"
|
|
" created_at timestamp DEFAULT current_timestamp,"
|
|
" unique(module, step)"
|
|
");")]
|
|
(jdbc/execute! conn [sql])
|
|
nil))
|
|
|
|
(defn migrate!
|
|
"Main entry point for apply a migration."
|
|
([conn migrations]
|
|
(impl-migrate conn migrations nil))
|
|
([conn migrations options]
|
|
(impl-migrate conn migrations options)))
|
|
|
|
(defn resource
|
|
"Helper for setup migration functions
|
|
just using a simple path to sql file
|
|
located in the class path."
|
|
[path]
|
|
(fn [pool]
|
|
(let [sql (slurp (io/resource path))]
|
|
(jdbc/execute! pool [sql])
|
|
true)))
|