diff --git a/src/metabase/core.clj b/src/metabase/core.clj index 60ab7c9f2e2186527a1b463d1ed49eaebb30d4a9..ef5156a431ff4aec37044e3c8f943227c1bc83b8 100644 --- a/src/metabase/core.clj +++ b/src/metabase/core.clj @@ -20,7 +20,8 @@ [routes :as routes] [sample-data :as sample-data] [setup :as setup] - [task :as task]) + [task :as task] + [util :as u]) (metabase.models [setting :refer [defsetting]] [database :refer [Database]] [user :refer [User]]))) @@ -67,6 +68,10 @@ wrap-session ; reads in current HTTP session and sets :session/key wrap-gzip)) ; GZIP response if client can handle it + +;;; ## ---------------------------------------- LIFECYCLE ---------------------------------------- + + (defn- -init-create-setup-token "Create and set a new setup token, and open the setup URL on the user's system." [] @@ -127,7 +132,8 @@ true) -;; ## Jetty (Web) Server +;;; ## ---------------------------------------- Jetty (Web) Server ---------------------------------------- + (def ^:private jetty-instance (atom nil)) @@ -157,9 +163,10 @@ (reset! jetty-instance nil))) -(defn -main - "Launch Metabase in standalone mode." - [& args] +;;; ## ---------------------------------------- App Main ---------------------------------------- + + +(defn- start-normally [] (log/info "Starting Metabase in STANDALONE mode") (try ;; run our initialization process @@ -169,3 +176,21 @@ (catch Exception e (.printStackTrace e) (log/error "Metabase Initialization FAILED: " (.getMessage e))))) + +(defn- run-cmd [cmd & args] + (let [cmd->fn {:migrate (fn [direction] + (db/migrate (keyword direction)))}] + (if-let [f (cmd->fn cmd)] + (do (apply f args) + (println "Success.") + (System/exit 0)) + (do (println "Unrecognized command:" (name cmd)) + (println "Valid commands are:\n" (u/pprint-to-str (map name (keys cmd->fn)))) + (System/exit 1))))) + +(defn -main + "Launch Metabase in standalone mode." + [& [cmd & args]] + (if cmd + (apply run-cmd (keyword cmd) args) ; run a command like `java -jar metabase.jar migrate release-locks` or `lein run migrate release-locks` + (start-normally))) ; with no command line args just start Metabase normally diff --git a/src/metabase/db.clj b/src/metabase/db.clj index b10bca61cb3c577d442862e25ab29c1c1f7c89f2..492594f028863afeb2ee914fbf13e8f7093853f3 100644 --- a/src/metabase/db.clj +++ b/src/metabase/db.clj @@ -64,21 +64,31 @@ "migrations/liquibase.json") (defn migrate - "Migrate the database `:up`, `:down`, or `:print`." - [jdbc-connection-details direction] - (try - (jdbc/with-db-transaction [conn jdbc-connection-details] - (let [^Database database (-> (DatabaseFactory/getInstance) - (.findCorrectDatabaseImplementation (JdbcConnection. (jdbc/get-connection conn)))) - ^Liquibase liquibase (Liquibase. changelog-file (ClassLoaderResourceAccessor.) database)] - (case direction - :up (.update liquibase "") - :down (.rollback liquibase 10000 "") - :print (let [writer (StringWriter.)] - (.update liquibase "" writer) - (.toString writer))))) - (catch Throwable e - (throw (DatabaseException. e))))) + "Migrate the database: + + * `:up` - Migrate up + * `:down` - Rollback *all* migrations + * `:print` - Just print the SQL for running the migrations, don't actually run them. + * `:release-locks` - Manually release migration locks left by an earlier failed migration. + (This shouldn't be necessary now that we run migrations inside a transaction, + but is available just in case)." + ([direction] + (migrate @jdbc-connection-details direction)) + ([jdbc-connection-details direction] + (try + (jdbc/with-db-transaction [conn jdbc-connection-details] + (let [^Database database (-> (DatabaseFactory/getInstance) + (.findCorrectDatabaseImplementation (JdbcConnection. (jdbc/get-connection conn)))) + ^Liquibase liquibase (Liquibase. changelog-file (ClassLoaderResourceAccessor.) database)] + (case direction + :up (.update liquibase "") + :down (.rollback liquibase 10000 "") + :print (let [writer (StringWriter.)] + (.update liquibase "" writer) + (.toString writer)) + :release-locks (.forceReleaseLocks liquibase)))) + (catch Throwable e + (throw (DatabaseException. e)))))) ;; ## SETUP-DB @@ -122,10 +132,10 @@ ;; Run through our DB migration process and make sure DB is fully prepared (if auto-migrate - (migrate @jdbc-connection-details :up) + (migrate :up) ;; if we are not doing auto migrations then print out migration sql for user to run manually ;; then throw an exception to short circuit the setup process and make it clear we can't proceed - (let [sql (migrate @jdbc-connection-details :print)] + (let [sql (migrate :print)] (log/info (str "Database Upgrade Required\n\n" "NOTICE: Your database requires updates to work with this version of Metabase. " "Please execute the following sql commands on your database before proceeding.\n\n"