use anyhow::Result;
use crate::db;
pub(in crate::cli) fn run_status() -> Result<()> {
let conn = db::open_db()?;
let db_path = db::db_path();
let db_size = std::fs::metadata(&db_path)
.map(|metadata| metadata.len())
.unwrap_or(0);
let version = env!("CARGO_PKG_VERSION");
let stats = db::query_system_stats(&conn)?;
let today_start = chrono::Local::now()
.date_naive()
.and_hms_opt(0, 0, 0)
.map(|dt| dt.and_utc().timestamp())
.unwrap_or(0);
let daily_stats = db::query_daily_activity_stats(&conn, today_start)?;
let top_projects = db::query_top_projects(&conn, 5)?;
println!("remem v{}", version);
println!(
"Database: {} ({:.1} MB)",
db_path.display(),
db_size as f64 / 1_048_576.0
);
println!();
println!(" Memories: {:>6}", stats.active_memories);
println!(" Observations: {:>6}", stats.active_observations);
println!(" Sessions: {:>6}", stats.session_summaries);
println!(" Raw messages: {:>6}", stats.raw_messages);
println!();
println!("Capture pipeline:");
println!(" Captured: {:>6}", stats.captured_events);
println!(" Extract todo: {:>6}", stats.pending_extraction_tasks);
println!(" Extract run: {:>6}", stats.processing_extraction_tasks);
println!(" Extract fail: {:>6}", stats.failed_extraction_tasks);
println!(" Candidates: {:>6}", stats.pending_memory_candidates);
if let Some(epoch) = stats.oldest_pending_extraction_epoch {
let age_secs = chrono::Utc::now().timestamp().saturating_sub(epoch);
println!(" Oldest task: {:>6}s", age_secs);
}
println!();
println!("Pending observations:");
println!(" Ready: {:>6}", stats.ready_pending_observations);
println!(" Delayed: {:>6}", stats.delayed_pending_observations);
println!(
" Processing: {:>6}",
stats.processing_pending_observations
);
println!(
" Expired: {:>6}",
stats.expired_processing_pending_observations
);
println!(" Failed: {:>6}", stats.failed_pending_observations);
if let Some(epoch) = stats.oldest_ready_pending_epoch {
let age_secs = chrono::Utc::now().timestamp().saturating_sub(epoch);
println!(" Oldest ready: {:>6}s", age_secs);
}
println!();
println!("Jobs:");
println!(" Pending: {:>6}", stats.pending_jobs);
println!(" Processing: {:>6}", stats.processing_jobs);
println!(" Failed: {:>6}", stats.failed_jobs);
println!(" Stuck: {:>6}", stats.stuck_jobs);
println!();
println!("Worker daemon:");
let daemon_health = if stats.worker_daemon_healthy {
"healthy"
} else if stats.worker_heartbeat_age_secs.is_some() {
"stale"
} else {
"missing"
};
println!(" Health: {:>7}", daemon_health);
if let Some(age_secs) = stats.worker_heartbeat_age_secs {
println!(" Last beat: {:>6}s", age_secs);
}
if let Some(owner) = &stats.worker_heartbeat_owner {
println!(" Owner: {}", owner);
}
println!();
println!("Today:");
println!(" New memories: {:>4}", daily_stats.memories);
println!(" New observations: {:>4}", daily_stats.observations);
if !top_projects.is_empty() {
println!();
println!("Top projects:");
for project in &top_projects {
println!(" {:>4} {}", project.count, project.project);
}
}
println!();
for line in crate::db::schema::status::format_summary() {
println!("{}", line);
}
Ok(())
}