use super::tables::{
count_rows, first_existing_table, CHUNK_EMBEDDING_TABLES, ENTITY_EMBEDDING_TABLES,
MEMORY_EMBEDDING_TABLES,
};
pub(super) fn llm_slot_info() -> (u32, u32, u32) {
let max = crate::llm_slots::default_max_concurrency();
let status = crate::llm_slots::read_status(max);
let stale = crate::llm_slots::find_stale_slots(max);
(status.max, status.active, stale.len() as u32)
}
pub(super) fn memory_embedding_health(conn: &rusqlite::Connection) -> (bool, i64, i64, i64) {
let Some(table_name) = first_existing_table(conn, MEMORY_EMBEDDING_TABLES) else {
return (false, 0, 0, 0);
};
let total = count_rows(conn, table_name);
let missing = conn
.query_row(
&format!(
"SELECT COUNT(*)
FROM memories m
LEFT JOIN {table_name} me ON me.memory_id = m.id
WHERE me.memory_id IS NULL AND m.deleted_at IS NULL"
),
[],
|r| r.get(0),
)
.unwrap_or(0);
let orphaned = conn
.query_row(
&format!(
"SELECT COUNT(*)
FROM {table_name} me
LEFT JOIN memories m ON m.id = me.memory_id
WHERE m.id IS NULL OR m.deleted_at IS NOT NULL"
),
[],
|r| r.get(0),
)
.unwrap_or(0);
(true, total, missing, orphaned)
}
pub(super) fn entity_embedding_health(conn: &rusqlite::Connection) -> (bool, i64) {
let Some(table_name) = first_existing_table(conn, ENTITY_EMBEDDING_TABLES) else {
return (false, 0);
};
let missing = conn
.query_row(
&format!(
"SELECT COUNT(*)
FROM entities e
LEFT JOIN {table_name} ee ON ee.entity_id = e.id
WHERE ee.entity_id IS NULL"
),
[],
|r| r.get(0),
)
.unwrap_or(0);
(true, missing)
}
pub(super) fn chunk_embedding_health(conn: &rusqlite::Connection) -> (bool, i64) {
let Some(table_name) = first_existing_table(conn, CHUNK_EMBEDDING_TABLES) else {
return (false, 0);
};
let missing = conn
.query_row(
&format!(
"SELECT COUNT(*)
FROM memory_chunks c
LEFT JOIN {table_name} ce ON ce.chunk_id = c.id
WHERE ce.chunk_id IS NULL"
),
[],
|r| r.get(0),
)
.unwrap_or(0);
(true, missing)
}
pub(super) fn coverage_pct(table_ok: bool, total: i64, missing: i64) -> f64 {
if total <= 0 {
return 100.0;
}
if !table_ok {
return 0.0;
}
let covered = (total - missing).max(0) as f64;
(covered / total as f64) * 100.0
}