///|
/// Event kind emitted by a `TTL` cache.
pub(all) enum EventKind {
/// A key was found and has not expired.
Hit
/// A key was not found, or was expired before the read completed.
Miss
/// A key expired during lazy cleanup.
Expired
/// A new key was rejected because the cache was at capacity.
Drop
/// A key was added or replaced.
Set
/// A key was removed manually, by replacement, by clear, or by expiry.
Del
} derive(Debug, Eq, Hash)
///|
/// Event payload passed to cache listeners.
pub(all) struct TTLEvent[T] {
kind : EventKind
key : String
val : T?
expire_ms : Int64?
} derive(Debug, Eq)
///|
/// Item returned by `TTL::entries`.
pub(all) struct CacheEntry[T] {
key : String
val : T
expire_ms : Int64
} derive(Debug, Eq)
///|
/// Item accepted by `TTL::mset`.
pub(all) struct SetEntry[T] {
key : String
val : T
ttl_ms : Int64?
} derive(Debug, Eq)
///|
/// Creates an entry for `TTL::mset`.
pub fn[T] SetEntry::new(key : String, val : T, ttl_ms? : Int64) -> SetEntry[T] {
{ key, val, ttl_ms }
}
///|
struct Item[T] {
val : T
expire_ms : Int64
}
///|
struct Listener[T] {
id : Int
callback : (TTLEvent[T]) -> Unit
}
///|
/// A generic in-memory time-to-live cache.
///
/// The cache is runtime-neutral: callers pass `now_ms` to methods that need a
/// clock. Expired values are removed lazily on reads or explicit cleanup.
pub struct TTL[T] {
store : Map[String, Item[T]]
listeners : Map[EventKind, Array[Listener[T]]]
mut default_ttl_ms : Int64
mut capacity : Int
mut next_listener_id : Int
}