Bounded atom primitive — size-limited, TTL-aware map atoms.
Wraps a standard Clojure atom holding a map of entries, enforcing:
Each entry is stored as: key -> {:data X :created-at T :last-accessed T}
Designed to replace unbounded defonce atoms that grow without limit, causing GC pressure and eventual OOM/death-spiral.
Usage: (def my-store (bounded-atom {:max-entries 1000 :ttl-ms 300000 :eviction-policy :lru}))
(bput! my-store :key-1 {:task "X"}) (bget my-store :key-1)
Global sweep: (register-sweepable! my-store :my-store) (sweep-all!) ;; evicts expired entries from all registered atoms
Auto-sweep scheduler: (start-sweep-scheduler! {:interval-ms 60000}) ;; sweep every 60s (sweep-scheduler-status) ;; check scheduler state (stop-sweep-scheduler!) ;; stop background sweep
Observability hooks: :on-evict — (fn [{:keys [name evicted-count reason entries]}]) called after evictions :on-sweep — (fn [{:keys [name evicted-count remaining duration-ms]}]) called after sweep
Bounded atom primitive — size-limited, TTL-aware map atoms.
Wraps a standard Clojure atom holding a map of entries, enforcing:
- Maximum entry count (eviction on overflow)
- TTL-based expiry (entries older than ttl-ms evicted on access)
- Eviction policies: :lru (least recently accessed), :fifo (oldest created), :ttl (expired only)
Each entry is stored as: key -> {:data X :created-at T :last-accessed T}
Designed to replace unbounded defonce atoms that grow without limit,
causing GC pressure and eventual OOM/death-spiral.
Usage:
(def my-store (bounded-atom {:max-entries 1000
:ttl-ms 300000
:eviction-policy :lru}))
(bput! my-store :key-1 {:task "X"})
(bget my-store :key-1)
Global sweep:
(register-sweepable! my-store :my-store)
(sweep-all!) ;; evicts expired entries from all registered atoms
Auto-sweep scheduler:
(start-sweep-scheduler! {:interval-ms 60000}) ;; sweep every 60s
(sweep-scheduler-status) ;; check scheduler state
(stop-sweep-scheduler!) ;; stop background sweep
Observability hooks:
:on-evict — (fn [{:keys [name evicted-count reason entries]}]) called after evictions
:on-sweep — (fn [{:keys [name evicted-count remaining duration-ms]}]) called after sweep(bclear! batom)Clear all entries from the bounded atom.
Clear all entries from the bounded atom.
(bcount batom)Return the number of entries in the bounded atom.
Return the number of entries in the bounded atom.
(bget batom k)Get entry data by key. Touches the entry (updates :last-accessed). Returns the data value or nil if not found / expired.
Get entry data by key. Touches the entry (updates :last-accessed). Returns the data value or nil if not found / expired.
(bkeys batom)Return the keys of the bounded atom.
Return the keys of the bounded atom.
(bounded-atom {:keys [max-entries ttl-ms eviction-policy on-evict on-sweep name]
:or {eviction-policy :lru}
:as opts})Create a bounded atom — a map-valued atom with size and TTL limits.
Options: :max-entries — maximum number of entries (required) :ttl-ms — time-to-live in milliseconds (nil = no TTL) :eviction-policy — :lru, :fifo, or :ttl (default :lru) :on-evict — optional callback (fn [{:keys [name evicted-count reason entries]}]) called after evictions during bput!/bounded-swap!/bounded-reset! :on-sweep — optional callback (fn [{:keys [name evicted-count remaining duration-ms]}]) called after sweep! completes :name — optional string name for this atom (used in callbacks and metrics)
Returns a map: {:atom (atom {}) ;; the underlying atom :opts {:max-entries N ...} ;; config for enforcement :name "my-store"} ;; optional name for observability
Create a bounded atom — a map-valued atom with size and TTL limits.
Options:
:max-entries — maximum number of entries (required)
:ttl-ms — time-to-live in milliseconds (nil = no TTL)
:eviction-policy — :lru, :fifo, or :ttl (default :lru)
:on-evict — optional callback (fn [{:keys [name evicted-count reason entries]}])
called after evictions during bput!/bounded-swap!/bounded-reset!
:on-sweep — optional callback (fn [{:keys [name evicted-count remaining duration-ms]}])
called after sweep! completes
:name — optional string name for this atom (used in callbacks and metrics)
Returns a map:
{:atom (atom {}) ;; the underlying atom
:opts {:max-entries N ...} ;; config for enforcement
:name "my-store"} ;; optional name for observability(bounded-reset! batom new-map)Bulk replacement with size check. new-map must be a map of key -> {:data X :created-at T :last-accessed T}. Entries exceeding max-entries are evicted per policy.
Returns {:result new-val :evicted-count N :eviction-reason reason}. Fires :on-evict callback if evictions occurred.
Bulk replacement with size check. new-map must be a map of
key -> {:data X :created-at T :last-accessed T}.
Entries exceeding max-entries are evicted per policy.
Returns {:result new-val :evicted-count N :eviction-reason reason}.
Fires :on-evict callback if evictions occurred.(bounded-swap! batom f & args)Like swap! but enforces max-entries, evicting per policy when full. f receives the current entry-map and must return a new entry-map. Raw entries are maps of key -> {:data X :created-at T :last-accessed T}.
Returns {:result new-val :evicted-count N :eviction-reason reason}. Fires :on-evict callback if evictions occurred.
Like swap! but enforces max-entries, evicting per policy when full.
f receives the current entry-map and must return a new entry-map.
Raw entries are maps of key -> {:data X :created-at T :last-accessed T}.
Returns {:result new-val :evicted-count N :eviction-reason reason}.
Fires :on-evict callback if evictions occurred.(bput! batom k data)Put a single entry. Enforces capacity, evicting per policy when full. Returns {:result new-val :evicted-count N :eviction-reason reason}. Fires :on-evict callback if evictions occurred.
Put a single entry. Enforces capacity, evicting per policy when full.
Returns {:result new-val :evicted-count N :eviction-reason reason}.
Fires :on-evict callback if evictions occurred.(register-sweepable! batom name-kw)Register a bounded atom in the global sweep registry. name-kw is a keyword identifier for diagnostics.
Register a bounded atom in the global sweep registry. name-kw is a keyword identifier for diagnostics.
(registered-sweepables)Return the map of all registered sweepable bounded atoms.
Return the map of all registered sweepable bounded atoms.
(start-sweep-scheduler!)(start-sweep-scheduler! {:keys [interval-ms on-sweep-complete]
:or {interval-ms 300000}})Start periodic sweep of all registered bounded atoms. Returns a stop function. Idempotent — second call is no-op.
Options: :interval-ms — sweep interval in milliseconds (default: 300000 = 5 min) :on-sweep-complete — optional callback (fn [results]) called after each sweep with the vector of per-atom sweep stats
Start periodic sweep of all registered bounded atoms.
Returns a stop function. Idempotent — second call is no-op.
Options:
:interval-ms — sweep interval in milliseconds (default: 300000 = 5 min)
:on-sweep-complete — optional callback (fn [results]) called after each sweep
with the vector of per-atom sweep stats(stop-sweep-scheduler!)Stop periodic sweep. Idempotent.
Stop periodic sweep. Idempotent.
(sweep! batom name-kw)Evict expired entries from a single bounded atom. Returns {:name name-kw :evicted-count N :remaining N :duration-ms N}. Fires :on-sweep callback if configured.
Evict expired entries from a single bounded atom.
Returns {:name name-kw :evicted-count N :remaining N :duration-ms N}.
Fires :on-sweep callback if configured.(sweep-all!)Iterate all registered bounded atoms, evict expired entries. Returns vector of per-atom stats.
Iterate all registered bounded atoms, evict expired entries. Returns vector of per-atom stats.
(sweep-scheduler-status)Return {:running? bool :interval-ms N :last-sweep-at inst :sweep-count N}
Return {:running? bool :interval-ms N :last-sweep-at inst :sweep-count N}
(unregister-sweepable! name-kw)Remove a bounded atom from the sweep registry.
Remove a bounded atom from the sweep registry.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |