### Cache Size Tuning Examples Source: https://github.com/clojure/core.cache/blob/master/_autodocs/configuration.md Provides example configurations for cache thresholds based on expected entry counts. Adjust the threshold to optimize performance for small, medium, or large caches. ```clojure ; Small caches (< 100 entries) :threshold 64 ``` ```clojure ; Medium caches (100-1000 entries) :threshold 256 ``` ```clojure ; Large caches (> 1000 entries) :threshold 2048 ``` -------------------------------- ### through-cache Function Examples Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-core-functions.md Shows examples of using `through-cache` with `swap!`, including a simple miss computation and a case involving a custom wrapper function. ```clojure (require '[clojure.core.cache :as cache]) (def c (atom (cache/lru-cache-factory {}))) ; Much cleaner with swap! (swap! c cache/through-cache :user-1 (fn [_] (db/fetch-user 1))) (swap! c cache/through-cache :user-2 compute-wrapper (fn [_] (db/fetch-user 2))) ``` -------------------------------- ### Complete Usage Example for LRU Cache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-wrapped.md Demonstrates creating an LRU cache, defining a data fetcher, and using lookup-or-miss for caching. Includes examples of manual cache operations like checking size and evicting entries. ```clojure (require '[clojure.core.cache.wrapped :as w]) ; Create a cache (def user-cache (w/lru-cache-factory {} :threshold 1000)) ; Define a data fetcher (defn fetch-user-from-db [user-id] (println (str "Fetching user " user-id " from DB...")) {:id user-id :name (str "User " user-id)}) ; Main function using the cache (defn get-user [user-id] (w/lookup-or-miss user-cache user-id (fn [_] (fetch-user-from-db user-id)))) ; Usage (get-user 1) ; Fetches from DB and caches (get-user 1) ; Returns cached value (get-user 2) ; Fetches from DB for new user (get-user 2) ; Returns cached value ; Manual operations (w/has? user-cache 1) ; true (w/size user-cache) ; 2 (w/evict user-cache 1) ; Remove user 1 (w/lookup user-cache 1) ; nil ``` -------------------------------- ### Configure LIRSCache for different workloads Source: https://github.com/clojure/core.cache/blob/master/_autodocs/configuration.md Provides example configurations for LIRSCache tailored to specific workloads: memory-constrained, web applications, and data processing. These examples demonstrate how to tune S and Q limits for optimal performance. ```clojure (require '[clojure.core.cache.wrapped :as w]) (w/lirs-cache-factory \ {} \ :s-history-limit 16 \ :q-history-limit 4) ``` ```clojure (require '[clojure.core.cache.wrapped :as w]) (w/lirs-cache-factory \ {} \ :s-history-limit 100 \ :q-history-limit 10) ``` ```clojure (require '[clojure.core.cache.wrapped :as w]) (w/lirs-cache-factory \ {} \ :s-history-limit 1000 \ :q-history-limit 100) ``` -------------------------------- ### through Function Examples Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-core-functions.md Demonstrates the different forms of the `through` function: basic hit/miss check, computing a value on miss, and wrapping the computation. ```clojure (require '[clojure.core.cache :as cache]) (def c (cache/basic-cache-factory {:a 1})) ; 1-arg form: just check hit/miss (def c' (cache/through c :a)) ;=> cache with :a hit ; 2-arg form: compute value on miss (def c'' (cache/through (fn [_] 42) c :b)) ;=> cache with :b set to 42 ; 3-arg form: wrap the computation (def c''' (cache/through (fn [f item] (f)) ; wrap-fn ignores item (fn [_] 99) ; value-fn c :c)) ;=> cache with :c set to 99 ``` -------------------------------- ### TTL Tuning Examples Source: https://github.com/clojure/core.cache/blob/master/_autodocs/configuration.md Demonstrates Time-To-Live (TTL) settings for cache entries in milliseconds. Configure TTL to manage data freshness for short-lived, medium-lived, or long-lived data. ```clojure ; Short-lived data (seconds) :ttl 5000 ``` ```clojure ; Medium-lived data (minutes) :ttl 60000 ``` ```clojure ; Long-lived data (hours) :ttl 3600000 ``` -------------------------------- ### Simple Query Cache Example Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-lru-cache.md Demonstrates using LRUCache to cache the last 100 database queries. It checks for cache hits, updates access times, and adds new results, evicting old ones if capacity is reached. ```clojure (require '[clojure.core.cache :as cache]) ; Cache last 100 queries (def query-cache (atom (cache/lru-cache-factory {} :threshold 100))) (defn get-user [id] (if (cache/has? @query-cache id) (do (swap! query-cache cache/hit id) (cache/lookup @query-cache id)) (let [user (db/fetch-user id)] (swap! query-cache cache/miss id user) user))) ``` -------------------------------- ### LIRS Tuning Examples Source: https://github.com/clojure/core.cache/blob/master/_autodocs/configuration.md Illustrates LIRS cache tuning parameters for different workload types. Adjust 's-history-limit' and 'q-history-limit' to optimize for temporal, frequency, or balanced access patterns. ```clojure ; For temporal workloads (recent = popular) :s-history-limit 96 :q-history-limit 4 ``` ```clojure ; For frequency workloads (popularity = use count) :s-history-limit 80 :q-history-limit 20 ``` ```clojure ; For balanced workloads :s-history-limit 90 :q-history-limit 10 ``` -------------------------------- ### Using FIFO Cache with Atom Source: https://github.com/clojure/core.cache/blob/master/README.md Demonstrates creating and manipulating an immutable FIFO cache wrapped in an atom. Use `swap!` for cache modifications and `get` for lookups. ```clojure (def C2 (atom (cache/fifo-cache-factory {:a 1, :b 2}))) (swap! C2 cache/through-cache :d (constantly 13)) ;=> {:a 1, :b 3, :d 13} (swap! C2 cache/evict :b) ;=> {:a 1, :d 13} (get @C2 :a) ``` -------------------------------- ### Wrapped API with TTL Cache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-ttl-cache.md Demonstrates using a wrapped TTL cache for automatic expiration handling. This example caches for 10 seconds and uses `lookup-or-miss` for safe, cache-stampede-free lookups. ```clojure (require '[clojure.core.cache.wrapped :as w]) ; Cache with 10-second TTL (def c (w/ttl-cache-factory {} :ttl 10000)) ; Safe, cache-stampede-free lookup (w/lookup-or-miss c endpoint (fn [_] (fetch-from-api endpoint))) ``` -------------------------------- ### Popular Items Cache Example Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-lu-cache.md Caches the 100 most frequently accessed products. Use this when you need to keep frequently accessed data readily available. ```clojure (require '[clojure.core.cache :as cache]) ; Cache 100 most-frequently-accessed products (def product-cache (atom (cache/lu-cache-factory {} :threshold 100))) (defn get-product [product-id] (let [cache-val (cache/lookup @product-cache product-id)] (if (some? cache-val) (do (swap! product-cache cache/hit product-id) cache-val) (let [product (db/fetch-product product-id)] (swap! product-cache cache/miss product-id product) product)))) ``` -------------------------------- ### Evicting Multiple Elements Source: https://github.com/clojure/core.cache/wiki/FIFO Adding multiple elements beyond the threshold will evict the oldest elements accordingly. This example evicts two elements when ':x' and ':z' are added. ```clojure (assoc C :x 36 :z 138) ;=> {:z 138, :x 36, :b 2} ``` -------------------------------- ### LRU Cache Eviction Example Source: https://github.com/clojure/core.cache/blob/master/docs/LRU.md Demonstrates how the LRU cache evicts the least recently used item when the threshold is exceeded. Accessing an item with `.hit` marks it as recently used. ```clojure (-> C (assoc :a 1) (assoc :b 2) (assoc :c 3)) ;=> {:b 2, :c 3} ``` ```clojure (-> C (assoc :a 1) (assoc :b 2) (.hit :a) ;; ensure :a is used most recently (assoc :c 3)) ;=> {:a 1, :c 3} ``` -------------------------------- ### Seed Cache with Initial Data Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-cache-protocol.md Initializes or reinitializes a cache with a map of key-value pairs. Use this to set up a cache with starting data or to reset it with new data. Note that if the seed data exceeds the cache's capacity, some entries may be dropped. ```clojure (require '[clojure.core.cache :as cache]) (def c (cache/lru-cache-factory {} :threshold 2)) ; Seed with initial data (def c' (cache/seed c {:a 1 :b 2 :c 3})) ; Resets the cache with new data (def c'' (cache/seed c' {:x 10 :y 20})) ``` -------------------------------- ### LRU Cache Eviction Example Source: https://github.com/clojure/core.cache/wiki/LRU Demonstrates how the LRU cache evicts the least recently used item when the threshold is exceeded. Accessing an item with `cache/hit` marks it as recently used. ```clojure (-> C (assoc :a 1) (assoc :b 2) (assoc :c 3)) ;=> {:b 2, :c 3} ``` ```clojure (-> C (assoc :a 1) (assoc :b 2) (cache/hit :a) ;; ensure :a is used most recently (assoc :c 3)) ;=> {:a 1, :c 3} ``` -------------------------------- ### Initialize and Use SoftCache with Wrapped API Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-soft-cache.md Shows how to initialize a SoftCache with initial values using the wrapped API and perform common operations like checking for key existence, retrieving values, adding new entries, removing entries, and safe lookups with fallback computation. ```clojure (require '[clojure.core.cache.wrapped :as w]) (def c (w/soft-cache-factory {:a 1})) (w/has? c :a) ;=> true (w/lookup c :a) ;=> 1 (w/miss c :b 2) ;=> cache updated (w/evict c :a) ;=> :a removed (w/lookup-or-miss c :c (fn [_] (compute))) ;=> safe lookup ``` -------------------------------- ### Create a FIFO Cache Instance Source: https://github.com/clojure/core.cache/wiki/Using Demonstrates creating a new First-In, First-Out (FIFO) cache, optionally pre-seeded with initial key-value pairs. ```clojure (def C (cache/fifo-cache-factory {:a 1, :b 2})) ``` -------------------------------- ### seed Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-lu-cache.md Creates a new LUCache initialized with a given map. All entries in the new cache start with a use count of 0. ```APIDOC ## seed ### Description Returns a new LUCache initialized with `base-map`. All entries start with use count 0. ### Method N/A (Function call) ### Endpoint N/A (Function call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | cache | LUCache | Yes | The existing cache instance (its threshold is preserved) | | base-map | map | Yes | The map of key-value pairs to initialize the new cache with | ### Return Type A new `LUCache` instance initialized with `base-map` and the same threshold as the original cache. ### Example ```clojure (def c (cache/lu-cache-factory {} :threshold 5)) (def c' (cache/seed c {:x 1 :y 2 :z 3})) ;=> cache with all entries at use count 0 ``` ``` -------------------------------- ### Manual Cache Management with Core API Source: https://github.com/clojure/core.cache/blob/master/_autodocs/INDEX.md Illustrates manual cache management using atoms and the core API, suitable for library code. It shows how to initialize a cache and update it using through-cache. ```clojure (require '[clojure.core.cache :as cache]) ; Manual cache management with atoms (def c (atom (cache/lru-cache-factory {}))) (swap! c cache/through-cache key (fn [_] (compute-value))) ``` -------------------------------- ### Custom LoggingCache Type Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-core-functions.md Example of creating a custom cache type that logs all cache operations. It implements the CacheProtocol and uses a map for storage. ```clojure (require '[clojure.core.cache :as cache]) ; Create a custom cache that logs all operations (cache/defcache LoggingCache [cache-map] CacheProtocol (lookup [_ item] (println (str "lookup: " item)) (get cache-map item)) (lookup [_ item not-found] (println (str "lookup: " item)) (get cache-map item not-found)) (has? [_ item] (println (str "has?: " item)) (contains? cache-map item)) (hit [this item] (println (str "hit: " item)) this) (miss [_ item result] (println (str "miss: " item)) (LoggingCache. (assoc cache-map item result))) (evict [_ item] (println (str "evict: " item)) (LoggingCache. (dissoc cache-map item))) (seed [_ base] (println (str "seed: " base)) (LoggingCache. base))) ; Use the custom cache (def c (LoggingCache. {})) (cache/miss c :a 1) ; prints "miss: :a" (cache/lookup c :a) ; prints "lookup: :a" returns 1 ``` -------------------------------- ### Create a SoftCache with Initial Data Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-soft-cache.md Initialize a SoftCache with key-value pairs by passing a map to `soft-cache-factory`. ```clojure (require '[clojure.core.cache :as cache]) ; Cache with initial data (def c2 (cache/soft-cache-factory {:a 1 :b 2})) ``` -------------------------------- ### Create FIFOCache with Large Initial Dataset and Small Threshold Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-fifo-cache.md Demonstrates creating a FIFOCache with an initial dataset that exceeds the specified threshold. Only the last 'threshold' entries are retained, showcasing the eviction behavior during initialization. ```clojure (require '[clojure.core.cache :as cache]) ; Large initial dataset (def c3 (cache/fifo-cache-factory {:x 1 :y 2 :z 3} :threshold 2)) ;=> Only last 2 entries retained: {:y 2 :z 3} ``` -------------------------------- ### LU Cache Eviction Example Source: https://github.com/clojure/core.cache/wiki/LU When the cache threshold is exceeded, the least used element is evicted. Accessing an element increases its 'hit count'. ```clojure (-> C (assoc :a 1) (assoc :b 2) (assoc :c 3)) ;=> {:b 2, :c 3} ``` ```clojure (-> C (assoc :a 1) (assoc :b 2) (cache/hit :b) (cache/hit :b) (cache/hit :a) ;; ensure :a is used most recently (assoc :c 3)) ;=> {:c 3, :b 2} ``` -------------------------------- ### Initialize and Use Wrapped LIRS Cache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-lirs-cache.md Shows how to create a LIRS cache using the wrapped API, which simplifies cache operations. It also demonstrates a common pattern of looking up a value or missing if it's not present, executing an expensive operation only on a miss. ```clojure (require '[clojure.core.cache.wrapped :as w]) (def c (w/lirs-cache-factory {} :s-history-limit 50 :q-history-limit 5)) (w/lookup-or-miss c key (fn [_] (expensive-operation))) ``` -------------------------------- ### Evicting the Oldest Element Source: https://github.com/clojure/core.cache/wiki/FIFO When the cache exceeds its threshold, adding a new element evicts the oldest one. This example shows the eviction of ':a' after adding ':d'. ```clojure (assoc C :d 42) ;=> {:c 3, :b 2, :d 42} ``` -------------------------------- ### LameCache Lookup Implementation Source: https://github.com/clojure/core.cache/blob/master/docs/Extending.md Provides the implementation for the lookup methods in LameCache, which simply delegate to the underlying Clojure map's get function. ```clojure (lookup [_ item] (get cache item)) (lookup [_ item not-found] (get cache item not-found)) ``` -------------------------------- ### Custom TransformCache Type Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-core-functions.md Example of creating a cache that applies a transformation function to values upon lookup. It implements the CacheProtocol and stores data in a map. ```clojure (require '[clojure.core.cache :as cache]) ; Create a cache that applies a transformation to values (cache/defcache TransformCache [cache-map transform-fn] CacheProtocol (lookup [_ item] (when-let [v (get cache-map item)] (transform-fn v))) (lookup [_ item not-found] (if (contains? cache-map item) (transform-fn (get cache-map item)) not-found)) (has? [_ item] (contains? cache-map item)) (hit [this item] this) (miss [_ item result] (TransformCache. (assoc cache-map item result) transform-fn)) (evict [_ item] (TransformCache. (dissoc cache-map item) transform-fn)) (seed [_ base] (TransformCache. base transform-fn))) ; Use it to cache and transform values (def c (TransformCache. {} (fn [v] (str "Cached: " v)))) (cache/miss c :x 42) (cache/lookup c :x) ;=> "Cached: 42" ``` -------------------------------- ### Create and Use a TTL Cache Source: https://github.com/clojure/core.cache/wiki/TTL Demonstrates how to create a TTL cache with a specific TTL value and add items to it. The cache will evict items older than the TTL. ```clojure (ns your.lib (:require [clojure.core.cache :as cache])) (def C (cache/ttl-cache-factory {} :ttl 1000)) (-> C (assoc :a 1) (assoc :b 2)) ;=> {:a 1, :b 2} ``` -------------------------------- ### Create and Use an Image Cache with Soft References Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-soft-cache.md Demonstrates creating a mutable SoftCache using an atom for storing images. Values are automatically evicted under memory pressure. Use `cache/lookup` to retrieve and `cache/miss` to add entries. ```clojure (require '[clojure.core.cache :as cache]) ; Large image cache that can be freed under memory pressure (def image-cache (atom (cache/soft-cache-factory {}))) (defn get-image [url] (let [cached (cache/lookup @image-cache url)] (if (some? cached) cached (let [image (load-image-from-url url)] (swap! image-cache cache/miss url image) image)))) ``` -------------------------------- ### Create a Basic Cache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/configuration.md Creates an unbounded, no-eviction cache. Use with caution for long-running systems due to unbounded growth. Accepts an initial map of key-value pairs. ```clojure (require '[clojure.core.cache :as cache]) ; Empty cache (cache/basic-cache-factory {}) ; With initial data (cache/basic-cache-factory {:user-1 {:name "Alice"} :user-2 {:name "Bob"}}) ``` -------------------------------- ### Get Data with Cache Transaction (through-cache) Source: https://github.com/clojure/core.cache/wiki/Using An alternative function for retrieving data that uses the cache/through-cache helper function within a swap! transaction for cache updates. ```clojure (defn get-data [key] (cache/lookup (swap! cache-store cache/through-cache key retrieve-data) key)) ``` -------------------------------- ### Initialize and Use LIRS Cache with Mixed Workloads Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-lirs-cache.md Demonstrates initializing a LIRS cache with specified history limits and a function to retrieve data, handling cache hits and misses. This is effective for workloads combining temporal and frequency access patterns. ```clojure (require '[clojure.core.cache :as cache]) ; LIRS is effective for mixed patterns ; (e.g., some frequently-accessed, some temporal) (def data-cache (atom (cache/lirs-cache-factory {} :s-history-limit 100 :q-history-limit 10))) (defn get-data [key] (if (cache/has? @data-cache key) (do (swap! data-cache cache/hit key) (cache/lookup @data-cache key)) (let [data (fetch-data key)] (swap! data-cache cache/miss key data) data))) ``` -------------------------------- ### Immutable Cache Usage with Clojure Core Cache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-overview.md Demonstrates creating and using an immutable FIFO cache from the clojure.core.cache namespace. Shows how to perform cache operations and manage state using atoms. ```clojure (require '[clojure.core.cache :as cache]) ; Create a cache (def c (cache/fifo-cache-factory {:a 1 :b 2})) ; Use the cache and get new cache back (def c' (cache/miss c :c 3)) ; Wrap in an atom for state management (def c-atom (atom c)) (swap! c-atom cache/evict :a) ``` -------------------------------- ### Basic Cache Usage with clojure.core.cache.wrapped Source: https://github.com/clojure/core.cache/blob/master/_autodocs/INDEX.md Demonstrates creating an LRU cache and performing common operations like lookup, size check, and manual eviction using the wrapped API. Use this for straightforward cache implementations. ```clojure (require '[clojure.core.cache.wrapped :as w]) ; Create cache (def c (w/lru-cache-factory {:a 1} :threshold 100)) ; Lookup with fallback to computation (w/lookup-or-miss c :key (fn [_] (expensive-operation))) ; Check size (w/size c) ; Manual operations (w/has? c :key) (w/miss c :new-key "value") (w/evict c :key) ``` -------------------------------- ### API Response Cache with TTL Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-ttl-cache.md Caches API responses for a specified duration (5 minutes in this example). Uses `has?` to check for valid entries and `miss` to add new responses. ```clojure (require '[clojure.core.cache :as cache]) ; Cache API responses for 5 minutes (def api-cache (atom (cache/ttl-cache-factory {} :ttl 300000))) (defn fetch-api [endpoint] (if (cache/has? @api-cache endpoint) (cache/lookup @api-cache endpoint) (let [response (http/get endpoint)] (swap! api-cache cache/miss endpoint response) response))) ``` -------------------------------- ### Create and Use LRUCache with Wrapped API Source: https://github.com/clojure/core.cache/blob/master/_autodocs/INDEX.md Demonstrates creating an LRUCache using the factory and safely accessing its values with lookup-or-miss. This is recommended for most applications due to its thread-safety and cache-stampede prevention. ```clojure (require '[clojure.core.cache.wrapped :as w]) ; Create a cache (def user-cache (w/lru-cache-factory {} :threshold 1000)) ; Use lookup-or-miss for safe, cache-stampede-free access (w/lookup-or-miss user-cache user-id (fn [_] (fetch-user-from-db user-id))) ``` -------------------------------- ### LU Cache Hit Demonstration Source: https://github.com/clojure/core.cache/blob/master/docs/LU.md Shows how the `.hit` operation influences eviction. Repeatedly hitting a key makes it less likely to be evicted, even if other items were added more recently. ```clojure (-> C (assoc :a 1) (assoc :b 2) (.hit :b) (.hit :b) (.hit :a) ;; ensure :a is used most recently (assoc :c 3)) ``` -------------------------------- ### Feature Flag Cache Example Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-lu-cache.md Caches feature flags used in hot paths with a threshold of 50. This is useful for quickly retrieving feature states without repeated configuration lookups. ```clojure (require '[clojure.core.cache :as cache]) ; Cache feature flags used in hot paths (def feature-cache (atom (cache/lu-cache-factory {} :threshold 50))) (defn feature-enabled? [feature-key] (w/lookup-or-miss feature-cache feature-key (fn [_] (config/get-feature-flag feature-key)))) ``` -------------------------------- ### through-cache Usage Pattern with swap! Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-core-functions.md Demonstrates the natural integration of `through-cache` with `swap!` for efficiently updating a cache managed by an atom, ensuring values are computed only on cache misses. ```clojure (require '[clojure.core.cache :as cache]) (def user-cache (atom (cache/lru-cache-factory {}))) (defn get-cached-user [user-id] ; Using through-cache works naturally with swap! (swap! user-cache cache/through-cache user-id (fn [_] (db/fetch-user user-id)))) ``` -------------------------------- ### Create TTLCacheQ with Default TTL Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-ttl-cache.md Creates a TTLCacheQ with the default time-to-live of 2000 milliseconds. Use this when a standard expiration period is suitable. ```clojure (require '[clojure.core.cache :as cache]) ; Default TTL of 2000ms (2 seconds) (def c1 (cache/ttl-cache-factory {})) ``` -------------------------------- ### Seed LIRSCache with Initial Data Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-lirs-cache.md Creates a new LIRSCache instance with specified history limits and initializes it with a given map of key-value pairs. This is useful for starting a cache with pre-existing data. ```clojure (def c (cache/lirs-cache-factory {} :s-history-limit 10 :q-history-limit 5)) (def c' (cache/seed c {:x 1 :y 2})) ``` -------------------------------- ### Wrapped API Usage with Clojure Core Cache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-overview.md Illustrates the recommended usage of the wrapped API from clojure.core.cache.wrapped. Shows how to create an atom-wrapped cache and perform operations like miss and lookup-or-miss. ```clojure (require '[clojure.core.cache.wrapped :as w]) ; Create an atom-wrapped cache (def c (w/fifo-cache-factory {:a 1 :b 2})) ; Operations modify the atom (w/miss c :c 3) ; Safe cache-stampede-free lookup (w/lookup-or-miss c :key (fn [_] (expensive-compute))) ``` -------------------------------- ### Get Data with Cache Transaction (has?/hit/miss) Source: https://github.com/clojure/core.cache/wiki/Using Provides a function that retrieves data, using a cache stored in an atom. It employs the has?/hit/miss pattern within a swap! transaction to update the cache. ```clojure (defn get-data [key] (cache/lookup (swap! cache-store #(if (cache/has? % key) (cache/hit % key) (cache/miss % key (retrieve-data key)))) key)) ``` -------------------------------- ### Associative Operations Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-cache-protocol.md Caches implementing CacheProtocol also implement Clojure's associative interfaces, allowing them to be used like regular maps for operations like assoc, dissoc, get, and count. ```APIDOC ## Associative Operations ### Description All caches implementing `CacheProtocol` also implement Clojure's associative interfaces, enabling map-like usage. ### Methods - **`(assoc cache k v)`** — Equivalent to `(miss cache k v)` - **`(dissoc cache k)`** — Equivalent to `(evict cache k)` - **`(get cache k)`** — Equivalent to `(lookup cache k)` - **`(get cache k not-found)`** — Equivalent to `(lookup cache k not-found)` - **`(count cache)`** — Returns the number of entries - **`(contains? cache k)`** — Equivalent to `(has? cache k)` ### Example ```clojure (def c (cache/basic-cache-factory {:a 1 :b 2})) (get c :a) ;=> 1 (assoc c :c 3) ;=> cache with :c => 3 (dissoc c :a) ;=> cache without :a (keys c) ;=> (:a :b) (vals c) ;=> (1 2) (count c) ;=> 2 (contains? c :a) ;=> true ``` ``` -------------------------------- ### Create a FIFO Cache Instance Source: https://github.com/clojure/core.cache/wiki/FIFO Use `fifo-cache-factory` to create a FIFO cache. You can provide an initial map and set a `:threshold` for eviction. The default threshold is 32. ```clojure (ns your.lib (:require [clojure.core.cache :as cache])) (def C (cache/fifo-cache-factory {:a 1, :b 2, :c 3} :threshold 3)) ``` -------------------------------- ### BasicCache associative operations Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-basic-cache.md BasicCache implements Clojure's associative interfaces, allowing standard map operations like `get`, `assoc`, `dissoc`, `count`, `keys`, `vals`, `contains?`, and `seq`. ```clojure (def c (cache/basic-cache-factory {:a 1 :b 2})) (get c :a) ;=> 1 (assoc c :c 3) ;=> cache with :c => 3 (dissoc c :a) ;=> cache without :a (count c) ;=> 2 (keys c) ;=> (:a :b) (vals c) ;=> (1 2) (contains? c :a) ;=> true (seq c) ;=> ([:a 1] [:b 2]) ``` -------------------------------- ### Core API Cache Usage with Atoms Source: https://github.com/clojure/core.cache/blob/master/_autodocs/INDEX.md Shows how to create and manage a cache using an atom and the core API for operations like lookup and miss handling. Suitable for scenarios requiring direct atom manipulation of the cache state. ```clojure (require '[clojure.core.cache :as cache]) ; Create cache in atom (def c (atom (cache/lru-cache-factory {}))) ; Lookup with miss handling (swap! c cache/through-cache :key (fn [_] (expensive-operation))) ; Direct operations (cache/lookup @c :key) (cache/has? @c :key) ``` -------------------------------- ### Get Approximate Cache Size Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-wrapped.md Use `size` to retrieve an approximate count of entries in the cache. Note that for some cache types like TTL, this count might be an overestimate as expired entries are not immediately removed. ```clojure (require '[clojure.core.cache.wrapped :as w]) (def c (w/lru-cache-factory {:a 1 :b 2} :threshold 100)) (w/size c) ;=> 2 ``` -------------------------------- ### Configure TTLCache for API response caching Source: https://github.com/clojure/core.cache/blob/master/_autodocs/configuration.md Configures a TTLCache to cache API responses for 5 minutes (300,000 milliseconds). This example shows how to use `lookup-or-miss` to fetch API data via HTTP if it's not found in the cache. ```clojure (require '[clojure.core.cache.wrapped :as w]) ; Cache API responses for 5 minutes (def api-cache (w/ttl-cache-factory {} :ttl 300000)) (defn fetch-api [endpoint] (w/lookup-or-miss api-cache endpoint (fn [_] (http/get endpoint)))) ``` -------------------------------- ### Composing FIFO and TTL Cache Factories Source: https://github.com/clojure/core.cache/blob/master/docs/Composing.md This snippet shows how to create a cache instance seeded with initial data and composed of a FIFO eviction policy and a TTL eviction policy. The cache is then used to demonstrate eviction behavior within and after the TTL window. ```clojure (def C (-> {:a 1 :b 2} (fifo-cache-factory :threshold 2) (ttl-cache-factory :ttl 5000))) ;; used right away (assoc C :c 42) ;;=> {:b 2, :c 42} ;; used after 5 seconds (assoc C :d 138) ;;=> {:d 138} ``` -------------------------------- ### Create Custom Cache Type with defcache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/types.md Demonstrates creating a custom cache type named CustomCache using the defcache macro, implementing the CacheProtocol. ```clojure (require '[clojure.core.cache :as cache]) (cache/defcache CustomCache [cache-map] CacheProtocol (lookup [_ item] (get cache-map item)) (lookup [_ item not-found] (get cache-map item not-found)) (has? [_ item] (contains? cache-map item)) (hit [this item] this) (miss [_ item result] (CustomCache. (assoc cache-map item result))) (evict [_ key] (CustomCache. (dissoc cache-map key))) (seed [_ base] (CustomCache. base))) ``` -------------------------------- ### Composing FIFO and TTL Caches Source: https://github.com/clojure/core.cache/wiki/Composing Initializes a cache with seed data, applies a FIFO eviction policy with a threshold, and then a TTL policy. This composition allows for both size-based eviction and time-based expiration. ```clojure (def C (-> {:a 1 :b 2} (fifo-cache-factory :threshold 2) (ttl-cache-factory :ttl 5000))) ``` ```clojure (assoc C :c 42) ;;=> {:b 2, :c 42} ``` ```clojure (assoc C :d 138) ;;=> {:d 138} ``` -------------------------------- ### Associative Operations on Cache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-cache-protocol.md Demonstrates using Clojure's associative operations with a cache. Caches implementing CacheProtocol support `get`, `assoc`, `dissoc`, `count`, and `contains?` like regular maps. Use `assoc` for adding or updating entries and `dissoc` for removing them. ```clojure (def c (cache/basic-cache-factory {:a 1 :b 2})) (get c :a) ;=> 1 (assoc c :c 3) ;=> cache with :c => 3 (dissoc c :a) ;=> cache without :a (keys c) ;=> (:a :b) (vals c) ;=> (1 2) (count c) ;=> 2 (contains? c :a) ;=> true ``` -------------------------------- ### Basic Immutable Cache Operations with Core.cache Source: https://github.com/clojure/core.cache/blob/master/README.md Demonstrates creating and manipulating an immutable FIFO cache. Use this for basic cache operations where you manage the cache's state explicitly. ```clojure (require '[clojure.core.cache :as cache]) ;; C1 is an immutable cache: (def C1 (cache/fifo-cache-factory {:a 1, :b 2})) (def C1' (if (cache/has? C1 :c) (cache/hit C1 :c) (cache/miss C1 :c 42))) ;=> {:a 1, :b 2, :c 42} (cache/lookup C1' :c) ;=> 42 (get C1' :c) ; cache/lookup is implemented as get ;=> 42 ;; a shorthand for the above conditional... (def C1' (cache/through-cache C1 :c (constantly 42))) ;; ...which uses a value to compute the result from the key... (cache/through-cache C1 my-key (partial jdbc/get-by-id db-spec :storage)) ;; ...so you could fetch values from a database if they're not in cache... (cache/evict C1 :b) ;=> {:a 1} ``` -------------------------------- ### Initialize Cache in Atom Source: https://github.com/clojure/core.cache/wiki/Using Shows how to create a mutable cache instance by storing a cache factory's result within a Clojure atom. ```clojure (defonce cache-store (atom (cache/lru-cache-factory {}))) ``` -------------------------------- ### Create BasicCache with basic-cache-factory Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-basic-cache.md Use `basic-cache-factory` to create an empty BasicCache or one initialized with a map of key-value pairs. Ensure the initial `base` is a non-nil map. ```clojure (require '[clojure.core.cache :as cache]) ; Empty cache (def c1 (cache/basic-cache-factory {})) ; Cache with initial data (def c2 (cache/basic-cache-factory {:a 1 :b 2 :c 3})) ``` -------------------------------- ### Basic SoftCache Operations with Wrapped API Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-soft-cache.md Illustrates fundamental SoftCache operations using the `clojure.core.cache.wrapped` API. This API provides a more conventional interface for cache interactions. ```clojure (require '[clojure.core.cache.wrapped :as w]) (def c (w/soft-cache-factory {})) (w/lookup c :key) ;=> value or nil (w/miss c :key (load-data)) ;=> cache updated (w/has? c :key) ;=> true or false (w/evict c :key) ;=> key removed ``` -------------------------------- ### Create a Basic Cache Atom Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-wrapped.md Use `basic-cache-factory` to create an atom that holds a BasicCache. This is suitable for simple key-value storage without advanced features like LRU or TTL. ```clojure (require '[clojure.core.cache.wrapped :as w]) (def c (w/basic-cache-factory {:a 1})) ;=> #atom[BasicCache {:a 1}] ``` -------------------------------- ### Create an LU Cache Instance Source: https://github.com/clojure/core.cache/wiki/LU Use `lu-cache-factory` to create an LU cache. An optional `:threshold` parameter can be provided; the default is 32. ```clojure (ns your.lib (:require [clojure.core.cache :as cache])) (def C (cache/lu-cache-factory {} :threshold 2)) (-> C (assoc :a 1) (assoc :b 2)) ;=> {:a 1, :b 2} ``` -------------------------------- ### URL Cache with FIFOCache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-fifo-cache.md Implement a URL cache using FIFOCache to store fetched content. When a URL is requested, it's first checked in the cache; if not found, it's fetched, stored, and then returned. The cache automatically evicts the oldest entries when the threshold is reached. ```clojure (require '[clojure.core.cache :as cache]) ; Cache last 100 URLs fetched (def url-cache (atom (cache/fifo-cache-factory {} :threshold 100))) (defn fetch-url [url] (let [result (if (cache/has? @url-cache url) (cache/lookup @url-cache url) (http/get url))] (swap! url-cache cache/miss url result) result)) ``` -------------------------------- ### Create LUCache Instance Source: https://github.com/clojure/core.cache/blob/master/docs/LU.md Use `lu-cache-factory` to create a new LU cache instance. An optional `:threshold` parameter can be provided; the default is 32. ```clojure (ns your.lib (:require [clojure.core.cache :as cache])) (def C (cache/lu-cache-factory {} :threshold 2)) (-> C (assoc :a 1) (assoc :b 2)) ``` -------------------------------- ### Create empty SoftCache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/configuration.md Creates an empty SoftCache with no configuration options. SoftCaches are mutable, thread-safe, and allow values to be garbage collected under memory pressure. ```clojure (cache/soft-cache-factory {}) ``` -------------------------------- ### miss Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-basic-cache.md Adds or updates a key-value pair in the cache, returning a new cache instance. BasicCache does not perform eviction. ```APIDOC ## Function: miss ### Description Returns a new `BasicCache` with the `key`-`value` pair added or updated. Since `BasicCache` has no eviction policy, it will never remove entries due to size constraints. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **cache** (BasicCache) - Required - The cache instance. - **key** (any) - Required - The key to add or update. - **value** (any) - Required - The value to associate with the key. ### Return Type (BasicCache) - A new cache instance with the key-value pair added or updated. ### Example ```clojure (def c (cache/basic-cache-factory {:a 1})) (def c' (cache/miss c :b 2)) ;=> {:a 1, :b 2} ; Can add many entries without size limit (def c'' (cache/miss c' :c 3)) ;=> {:a 1, :b 2, :c 3} ``` ``` -------------------------------- ### Create TTLCache with default TTL Source: https://github.com/clojure/core.cache/blob/master/_autodocs/configuration.md Creates a TTLCache with the default time-to-live of 2000 milliseconds. Use this for general-purpose caching where entries should expire automatically. ```clojure (cache/ttl-cache-factory {}) ``` -------------------------------- ### Basic Wrapped API Operations Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-ttl-cache.md Illustrates fundamental operations on a wrapped TTL cache, including checking for existence (`has?`), retrieving values (`lookup`), adding new entries (`miss`), and performing safe lookups (`lookup-or-miss`). ```clojure (require '[clojure.core.cache.wrapped :as w]) (def c (w/ttl-cache-factory {:a 1} :ttl 5000)) (w/has? c :a) ;=> true (if within TTL) (w/lookup c :a) ;=> 1 (if within TTL, else nil) (w/miss c :b 2) ;=> stores :b with current timestamp (w/lookup-or-miss c :c (fn [_] (compute))) ;=> safe lookup ``` -------------------------------- ### Seeding a New SoftCache from an Existing One Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-soft-cache.md Illustrates seeding a new SoftCache (`c2`) from an existing one (`c1`). The process correctly dereferences the soft references from `c1` and re-wraps the values into new soft references for `c2`, ensuring proper value transfer. ```clojure (require '[clojure.core.cache :as cache]) (def c1 (cache/soft-cache-factory {:a 1 :b 2})) ; Seed c2 from c1 — values are properly extracted from soft refs (def c2 (cache/seed c1 {:x 10 :y 20})) ``` -------------------------------- ### Create TTLCacheQ with Custom TTL Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-ttl-cache.md Creates a TTLCacheQ with a specified time-to-live duration in milliseconds. Use this for caching data with a precise validity window. ```clojure (require '[clojure.core.cache :as cache]) ; Custom TTL of 5000ms (5 seconds) (def c2 (cache/ttl-cache-factory {:a 1} :ttl 5000)) ``` -------------------------------- ### Create a TTL Cache Instance Source: https://github.com/clojure/core.cache/blob/master/docs/TTL.md Use the `ttl-cache-factory` function to create a TTL cache. You can optionally specify the `:ttl` parameter in milliseconds; the default is 2000ms. ```clojure (ns your.lib (:require [clojure.core.cache :as cache])) (def C (cache/ttl-cache-factory {} :ttl 1000)) (-> C (assoc :a 1) (assoc :b 2)) ;=> {:a 1, :b 2} ``` -------------------------------- ### Create Wrapped LRU Cache Instance Source: https://github.com/clojure/core.cache/wiki/Using Shows how to create a Least Recently Used (LRU) cache that is automatically wrapped in an atom using the wrapped namespace factory function. ```clojure (defonce cache-store (cw/lru-cache-factory {})) ; factory returns new cache wrapped in atom ``` -------------------------------- ### Create an LRU Cache Instance Source: https://github.com/clojure/core.cache/wiki/LRU Use `lru-cache-factory` to create an LRUCache. An optional `:threshold` parameter can be provided; the default is 32. ```clojure (ns your.lib (:require [clojure.core.cache :as cache])) (def C (cache/lru-cache-factory {} :threshold 2)) (-> C (assoc :a 1) (assoc :b 2)) ;=> {:a 1, :b 2} ``` -------------------------------- ### Create an Empty SoftCache Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-soft-cache.md Use `soft-cache-factory` with an empty map to create a new, empty SoftCache instance. ```clojure (require '[clojure.core.cache :as cache]) ; Empty cache (def c1 (cache/soft-cache-factory {})) ``` -------------------------------- ### Testing core.cache in Clojure REPL Source: https://github.com/clojure/core.cache/wiki/Building This snippet demonstrates how to use the core.cache library within a Clojure REPL after building it. It shows the creation of a FIFO cache and adding elements. ```clojure (use 'clojure.core.cache) def c (fifo-cache-factory 1 {:a 42})) (-> c (assoc :b 1) (assoc :z 108)) ``` -------------------------------- ### Create FIFOCache with Custom Threshold Source: https://github.com/clojure/core.cache/blob/master/_autodocs/api-reference-fifo-cache.md Creates a new FIFOCache with a specified capacity threshold. Use this when you need to control the maximum number of entries before eviction begins. ```clojure (require '[clojure.core.cache :as cache]) ; Custom threshold of 5 (def c2 (cache/fifo-cache-factory {:a 1 :b 2} :threshold 5)) ``` -------------------------------- ### Create SoftCache using wrapped API Source: https://github.com/clojure/core.cache/blob/master/_autodocs/configuration.md Creates an empty SoftCache using the wrapped API. This provides an alternative instantiation method while retaining the SoftCache's properties of mutability and garbage collection. ```clojure (require '[clojure.core.cache.wrapped :as w]) (w/soft-cache-factory {}) ```