(ns metabase-enterprise.cache.strategies (:require [java-time.api :as t] [metabase.api.cache] [metabase.models.cache-config :as cache-config] [metabase.premium-features.core :refer [defenterprise defenterprise-schema]] [metabase.query-processor.middleware.cache-backend.db :as backend.db] [metabase.util.log :as log] [metabase.util.malli.registry :as mr] [toucan2.core :as t2])) | |
(set! *warn-on-reflection* true) | |
(comment metabase.api.cache/keep-me) | |
Data shape | |
(mr/def ::cache-strategy "Schema for a caching strategy used internally" [:and :metabase.api.cache/cache-strategy.base [:multi {:dispatch :type} [:nocache :metabase.api.cache/cache-strategy.nocache] [:ttl [:merge :metabase.api.cache/cache-strategy.ttl [:map [:invalidated-at {:optional true} some?]]]] [:duration [:merge :metabase.api.cache/cache-strategy.ee.duration [:map [:invalidated-at {:optional true} some?]]]] [:schedule [:merge :metabase.api.cache/cache-strategy.ee.schedule [:map [:invalidated-at {:optional true} some?]]]]]]) | |
Querying DB | |
(defenterprise-schema cache-strategy :- [:maybe ::cache-strategy] "Returns the granular cache strategy for a card." :feature :cache-granular-controls [card dashboard-id] (let [qs (for [[i model model-id] [[1 "question" (:id card)] [2 "dashboard" dashboard-id] [3 "database" (:database_id card)] [4 "root" 0]] :when model-id] {:from [:cache_config] :select [:id [[:inline i] :ordering]] :where [:and [:= :model [:inline model]] [:= :model_id model-id]]}) q {:from [[{:union-all qs} :unused_alias]] :select [:id] :order-by :ordering :limit [:inline 1]} item (t2/select-one :model/CacheConfig :id q)] (cache-config/card-strategy item card))) | |
Strategy execution | |
Generate prepared statement for a db cache backend for a given strategy | (defmulti ^:private fetch-cache-stmt-ee* {:arglists '([strategy query-hash conn])} (fn [strategy _hash _conn] (:type strategy))) |
(defmethod fetch-cache-stmt-ee* :ttl [strategy query-hash conn] (backend.db/fetch-cache-stmt-ttl strategy query-hash conn)) | |
(defmethod fetch-cache-stmt-ee* :duration [strategy query-hash conn] (if-not (and (:duration strategy) (:unit strategy)) (log/debugf "Caching strategy %s should have :duration and :unit" (pr-str strategy)) (let [duration (t/duration (:duration strategy) (keyword (:unit strategy))) duration-ago (t/minus (t/offset-date-time) duration) invalidated-at (t/max duration-ago (:invalidated-at strategy))] (backend.db/prepare-statement conn query-hash invalidated-at)))) | |
(defmethod fetch-cache-stmt-ee* :schedule [{:keys [invalidated-at] :as strategy} query-hash conn] (if-not invalidated-at (log/debugf "Caching strategy %s has not run yet" (pr-str strategy)) (backend.db/prepare-statement conn query-hash invalidated-at))) | |
(defmethod fetch-cache-stmt-ee* :nocache [_ _ _] nil) | |
Returns prepared statement to query for db cache backend. | (defenterprise fetch-cache-stmt :feature :cache-granular-controls [strategy query-hash conn] (fetch-cache-stmt-ee* strategy query-hash conn)) |