diff --git a/src/metabase/query_processor/middleware/cache.clj b/src/metabase/query_processor/middleware/cache.clj index 3923418bfbf97c12b1681d4281a1b7c441461e99..30b2a63cd138f1410b4f0e83128a8bf0781bd5f1 100644 --- a/src/metabase/query_processor/middleware/cache.clj +++ b/src/metabase/query_processor/middleware/cache.clj @@ -18,9 +18,12 @@ [config :as config] [public-settings :as public-settings] [util :as u]] + [metabase.plugins.classloader :as classloader] [metabase.query-processor.middleware.cache-backend.interface :as i] [metabase.query-processor.util :as qputil] - [metabase.util.date :as du])) + [metabase.util + [date :as du] + [i18n :refer [trs]]])) ;; TODO - Why not make this an option in the query itself? :confused: (def ^:dynamic ^Boolean *ignore-cached-results* @@ -31,13 +34,10 @@ ;;; ---------------------------------------------------- Backend ----------------------------------------------------- -(def ^:private backend-instance - (atom nil)) - (defn- valid-backend? [instance] (extends? i/IQueryProcessorCacheBackend (class instance))) (defn- get-backend-instance-in-namespace - "Return a valid query cache backend `instance` in BACKEND-NS-SYMB, or throw an Exception if none exists." + "Return a valid query cache backend instance in `backend-ns-symb`, or throw an Exception if none exists." ;; if for some reason the resolved var doesn't satisfy `IQueryProcessorCacheBackend` we'll reload the namespace ;; it belongs to and try one more time. ;; This fixes the issue in dev sessions where the interface namespace gets reloaded causing the cache implementation @@ -54,19 +54,23 @@ :else (throw (Exception. (format "%s/instance doesn't satisfy IQueryProcessorCacheBackend" backend-ns-symb))))))) -(defn- set-backend! - "Set the cache backend to the cache defined by the keyword BACKEND. +(defn- resolve-backend + "Get the cache backend to the cache defined by the keyword `backend`. (This should be something like `:db`, `:redis`, or `:memcached`. See the documentation in `metabase.query-processor.middleware.cache-backend.interface` for details on how this works.)" ([] - (set-backend! (config/config-kw :mb-qp-cache-backend))) + (resolve-backend (config/config-kw :mb-qp-cache-backend))) + ([backend] + (classloader/the-classloader) (let [backend-ns-symb (symbol (str "metabase.query-processor.middleware.cache-backend." (munge (name backend))))] (require backend-ns-symb) - (log/info "Using query processor cache backend:" (u/format-color 'blue backend) (u/emoji "💾")) - (reset! backend-instance (get-backend-instance-in-namespace backend-ns-symb))))) + (log/info (trs "Using query processor cache backend: {0}" (u/format-color 'blue backend)) (u/emoji "💾")) + (get-backend-instance-in-namespace backend-ns-symb)))) +(defonce ^:private backend-instance + (delay (resolve-backend))) ;;; ------------------------------------------------ Cache Operations ------------------------------------------------ @@ -130,7 +134,4 @@ ;; wait until we're actually going to use the cache before initializing the backend. We don't want to initialize ;; it when the files get compiled, because that would give it the wrong version of the ;; `IQueryProcessorCacheBackend` protocol - (do - (when-not @backend-instance - (set-backend!)) - (run-query-with-cache qp query respond raise canceled-chan))))) + (run-query-with-cache qp query respond raise canceled-chan))))