use super::engine::KvEngine;
use super::engine_helpers::{parse_expiry_key, table_key};
#[derive(Debug, Clone)]
pub struct ExpiredKey {
pub tenant_id: u32,
pub collection: String,
pub key: Vec<u8>,
}
#[derive(Debug, Clone, Default)]
pub struct KvStats {
pub total_entries: usize,
pub total_mem_bytes: usize,
pub collection_count: usize,
pub max_load_factor: f32,
pub is_rehashing: bool,
pub total_index_entries: usize,
pub expiry_queue_depth: usize,
pub expiry_backlog: usize,
}
impl KvEngine {
pub fn tick_expiry(&mut self, now_ms: u64) -> Vec<ExpiredKey> {
let batch = self.expiry.tick(now_ms);
let mut reaped = Vec::new();
for (composite_key, expire_at_ms) in &batch.expired {
if let Some((tid, collection, key)) = parse_expiry_key(composite_key)
&& let Some(table) = self.tables.get_mut(&table_key(tid, &collection))
&& table.reap_expired(&key, *expire_at_ms)
{
reaped.push(ExpiredKey {
tenant_id: tid,
collection,
key,
});
}
}
reaped
}
pub fn expiry_queue_depth(&self) -> usize {
self.expiry.len()
}
pub fn expiry_backlog(&self) -> usize {
self.expiry.backlog()
}
pub fn truncate(&mut self, tenant_id: u32, collection: &str) -> usize {
let tkey = table_key(tenant_id, collection);
let count = self.tables.get(&tkey).map(|t| t.len()).unwrap_or(0);
self.tables.remove(&tkey);
self.indexes.remove(&tkey);
count
}
pub fn total_entries(&self) -> usize {
self.tables.values().map(|t| t.len()).sum()
}
pub fn total_mem_usage(&self) -> usize {
self.tables.values().map(|t| t.mem_usage()).sum()
}
pub fn collection_len(&self, tenant_id: u32, collection: &str) -> usize {
let tkey = table_key(tenant_id, collection);
self.tables.get(&tkey).map(|t| t.len()).unwrap_or(0)
}
pub fn stats(&self) -> KvStats {
let mut total_entries = 0usize;
let mut total_mem = 0usize;
let mut total_index_entries = 0usize;
let mut is_rehashing = false;
let mut max_load_factor: f32 = 0.0;
for table in self.tables.values() {
total_entries += table.len();
total_mem += table.mem_usage();
if table.load_factor() > max_load_factor {
max_load_factor = table.load_factor();
}
if table.is_rehashing() {
is_rehashing = true;
}
}
for idx_set in self.indexes.values() {
for field in idx_set.indexed_fields() {
if let Some(idx) = idx_set.get_index(field) {
total_index_entries += idx.entry_count();
}
}
}
KvStats {
total_entries,
total_mem_bytes: total_mem,
collection_count: self.tables.len(),
max_load_factor,
is_rehashing,
total_index_entries,
expiry_queue_depth: self.expiry.len(),
expiry_backlog: self.expiry.backlog(),
}
}
}