Skip to content
Snippets Groups Projects
Unverified Commit 2d6d12c8 authored by Braden Shepherdson's avatar Braden Shepherdson Committed by GitHub
Browse files

[MLv2] Cache JS -> CLJS metadata conversion (#38375)

This previous got rebuilt from scratch over and over, since different
queries being handed the same JS `Metadata` instance were returning
completely separate `MetadataProvider`s.

The FE replaces the `Metadata` instance as new metadata arrives from the
BE, so the `metabase.lib.cache/side-channel-cache` which is attached to
the input object is implicitly invalidated when the old `Metadata` is
thrown away.
parent ffd18732
No related branches found
No related tags found
No related merge requests found
......@@ -10,19 +10,20 @@
If there is not already a key `subkey` in the map, calls `(f x)` and caches the value at `subkey`.
If there is a value at `subkey`, it is returned directly."
[subkey x f]
(comment subkey) ; Avoids lint warning for half-unused `subkey`.
#?(:clj (f x)
:cljs (if (or (object? x) (map? x))
(do
(when-not (.-__mbcache ^js x)
(set! (.-__mbcache ^js x) (atom {})))
(if-let [cache (.-__mbcache ^js x)]
(if-let [cached (get @cache subkey)]
cached
;; Cache miss - generate the value and cache it.
(let [value (f x)]
(swap! cache assoc subkey value)
value))
(f x)))
(f x))))
([subkey x f] (side-channel-cache subkey x f false))
([subkey x f force?]
(comment subkey, force?) ; Avoids lint warning for half-unused inputs.
#?(:clj (f x)
:cljs (if (or force? (object? x) (map? x))
(do
(when-not (.-__mbcache ^js x)
(set! (.-__mbcache ^js x) (atom {})))
(if-let [cache (.-__mbcache ^js x)]
(if-let [cached (get @cache subkey)]
cached
;; Cache miss - generate the value and cache it.
(let [value (f x)]
(swap! cache assoc subkey value)
value))
(f x)))
(f x)))))
......@@ -6,6 +6,7 @@
[goog]
[goog.object :as gobject]
[medley.core :as m]
[metabase.lib.cache :as lib.cache]
[metabase.lib.metadata.protocols :as lib.metadata.protocols]
[metabase.lib.util :as lib.util]
[metabase.util :as u]
......@@ -24,6 +25,7 @@
;;;
;;; where keys are a map of String ID => metadata
;; TODO: This is always wrapped with `keyword` in its usage so that may as well be memoized too.
(def ^:private ^{:arglists '([k])} memoized-kebab-key
"Even tho [[u/->kebab-case-en]] has LRU memoization, plain memoization is significantly faster, and since the keys
we're parsing here are bounded it's fine to memoize this stuff forever."
......@@ -506,8 +508,8 @@
(object-get "settings")
(object-get (name setting-key))))
(defn metadata-provider
"Use a `metabase-lib/metadata/Metadata` as a [[metabase.lib.metadata.protocols/MetadataProvider]]."
(defn- metadata-provider*
"Inner implementation for [[metadata-provider]], which wraps this with a cache."
[database-id unparsed-metadata]
(let [metadata (parse-metadata unparsed-metadata)]
(log/debug "Created metadata provider for metadata")
......@@ -535,6 +537,13 @@
form))
metadata)))))
(defn metadata-provider
"Use a `metabase-lib/metadata/Metadata` as a [[metabase.lib.metadata.protocols/MetadataProvider]]."
[database-id unparsed-metadata]
(lib.cache/side-channel-cache (str database-id) unparsed-metadata
(partial metadata-provider* database-id)
true #_force?))
(def parse-column
"Parses a JS column provided by the FE into a :metadata/column value for use in MLv2."
(parse-object-fn :field))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment