pub struct TenantLoader { /* private fields */ }Expand description
Tracks which tenants have been hydrated into memory, serializes concurrent first-loads of the same tenant, and accounts for the approximate bytes each loaded tenant occupies (Step 3 cache budget input).
loaded is the source of truth for “is this tenant warm?”. It’s
insert-only until Step 3 #2’s mark_unloaded (eviction) lands.
locks holds one Mutex per tenant ever queried. Concurrent
first-queries get the same Mutex; the second waiter re-checks
loaded after acquiring it (the standard double-checked-lock
pattern, sound here because loaded’s DashMap insert
happens-before the lock release).
bytes accumulates per-tenant resident-byte estimates as
events get spliced in via append_loaded_event. It’s the input
the budget-enforcement step (Step 3 #3) keys off — the LRU
eviction policy compares the sum of these counters against the
configured byte budget.
Implementations§
Source§impl TenantLoader
impl TenantLoader
pub fn new() -> Self
pub fn with_timeout(load_timeout: Duration) -> Self
Sourcepub fn set_byte_budget(&self, budget: u64)
pub fn set_byte_budget(&self, budget: u64)
Set the cache byte budget. 0 disables enforcement.
pub fn byte_budget(&self) -> u64
Sourcepub fn over_budget(&self) -> bool
pub fn over_budget(&self) -> bool
True iff a budget is set AND total resident bytes exceed it.
Sourcepub fn touch(&self, tenant_id: &str)
pub fn touch(&self, tenant_id: &str)
Mark tenant_id as just-used (LRU-Y end of the order).
Cheap — single DashMap insert. Called on every query that
touches this tenant. If the eviction policy picks an LRU
victim, the most-recently-touched tenants are last to go.
Sourcepub fn pick_lru_excluding(&self, excluded: &str) -> Option<String>
pub fn pick_lru_excluding(&self, excluded: &str) -> Option<String>
Pick the loaded tenant with the oldest last_used Instant,
excluding excluded (the freshly-loaded tenant we don’t
want to immediately evict — would thrash). Returns None if
no other tenant is loaded — the caller should accept the
over-budget state in that case (a single tenant whose data
alone exceeds the budget can’t be evicted in favor of
itself).
mark_loaded always stamps last_used, so every loaded
tenant has a touch timestamp by construction.
Sourcepub fn is_loaded(&self, tenant_id: &str) -> bool
pub fn is_loaded(&self, tenant_id: &str) -> bool
Fast path probe — true if a previous call to mark_loaded
has succeeded for this tenant.
Sourcepub fn mark_loaded(&self, tenant_id: &str)
pub fn mark_loaded(&self, tenant_id: &str)
Record that this tenant has been hydrated. Idempotent.
Also stamps a fresh last_used so the tenant immediately
participates in LRU ordering and isn’t picked as an
eviction victim before its first explicit touch.
Sourcepub fn mark_unloaded(&self, tenant_id: &str)
pub fn mark_unloaded(&self, tenant_id: &str)
Reverse of mark_loaded: forget that this tenant is in
memory and reset its byte counter to 0. The next call to
is_loaded returns false; the next ensure-load will
re-walk the tenant’s subtree from disk. Called by the
eviction path.
Sourcepub fn add_bytes(&self, tenant_id: &str, n: u64)
pub fn add_bytes(&self, tenant_id: &str, n: u64)
Add n bytes to the resident-size estimate for tenant_id.
Called once per event spliced into memory for that tenant.
The total is what the budget check compares against.
Sourcepub fn bytes_for(&self, tenant_id: &str) -> u64
pub fn bytes_for(&self, tenant_id: &str) -> u64
Resident-byte estimate for a single tenant. Returns 0 for tenants that have never been loaded (or that were evicted — once eviction lands the counter resets to 0).
Sourcepub fn total_bytes(&self) -> u64
pub fn total_bytes(&self) -> u64
Sum of resident-byte estimates across every loaded tenant — the input the budget check compares against. O(loaded tenants), expected to be small.
Sourcepub fn bytes_per_tenant(&self) -> Vec<(String, u64)>
pub fn bytes_per_tenant(&self) -> Vec<(String, u64)>
Snapshot of (tenant_id, bytes) pairs for every tenant
that has any resident bytes. Used by the eviction policy
to pick a victim and by metrics endpoints.
Sourcepub fn lock_for(&self, tenant_id: &str) -> Arc<Mutex<()>> ⓘ
pub fn lock_for(&self, tenant_id: &str) -> Arc<Mutex<()>> ⓘ
Get-or-insert the per-tenant Mutex used for singleflight
loading. The first caller for a given tenant creates the
Mutex; later callers see the same instance and serialize on
it. Returns an Arc so the caller can hold the lock guard
without keeping a borrow into the DashMap.