Skip to main content

offline_intelligence/api/
admin_api.rs

1//! Admin API endpoints
2//! 
3//! This module provides administrative functionality for system management.
4//! Currently a placeholder for future implementation.
5
6use axum::{
7    extract::State,
8    http::StatusCode,
9    response::IntoResponse,
10    Json,
11};
12use std::sync::{Arc, atomic::Ordering};
13use serde::{Deserialize, Serialize};
14
15use crate::shared_state::SharedState;
16
17/// System health response
18#[derive(Debug, Serialize)]
19pub struct HealthResponse {
20    pub status: String,
21    pub version: String,
22    pub uptime_seconds: u64,
23}
24
25/// Database statistics response
26#[derive(Debug, Serialize)]
27pub struct DbStatsResponse {
28    pub total_sessions: usize,
29    pub total_messages: usize,
30    pub total_summaries: usize,
31    pub database_size_bytes: u64,
32}
33
34/// Maintenance request
35#[derive(Debug, Deserialize)]
36pub struct MaintenanceRequest {
37    pub operation: String,
38    pub parameters: Option<serde_json::Value>,
39}
40
41
42// Store application start time as seconds since epoch
43static START_TIME: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
44
45fn init_start_time() {
46    let now: u64 = std::time::SystemTime::now()
47        .duration_since(std::time::UNIX_EPOCH)
48        .unwrap_or_else(|_| std::time::Duration::from_secs(0))
49        .as_secs();
50    START_TIME.store(now, Ordering::SeqCst);
51}
52
53fn get_uptime_seconds() -> u64 {
54    let start = START_TIME.load(Ordering::SeqCst);
55    if start == 0 {
56        // Initialize on first call
57        init_start_time();
58        return 0;
59    }
60    
61    let now = std::time::SystemTime::now()
62        .duration_since(std::time::UNIX_EPOCH)
63        .unwrap_or_else(|_| std::time::Duration::from_secs(0))
64        .as_secs();
65    
66    now.saturating_sub(start)
67}
68
69/// Health check endpoint
70pub async fn health(
71    State(_shared_state): State<Arc<SharedState>>,
72) -> Result<impl IntoResponse, StatusCode> {
73    // Initialize start time if not already set
74    if START_TIME.load(Ordering::SeqCst) == 0 {
75        init_start_time();
76    }
77    
78    Ok((
79        StatusCode::OK,
80        Json(HealthResponse {
81            status: "healthy".to_string(),
82            version: env!("CARGO_PKG_VERSION").to_string(),
83            uptime_seconds: get_uptime_seconds(),
84        }),
85    ))
86}
87
88/// Database statistics endpoint
89pub async fn db_stats(
90    State(shared_state): State<Arc<SharedState>>,
91) -> Result<impl IntoResponse, StatusCode> {
92    // Access the database to get actual statistics
93    let total_sessions = shared_state.conversations.counters.active_sessions.load(Ordering::Relaxed);
94    
95    let total_messages = shared_state.conversations.counters.processed_messages.load(Ordering::Relaxed);
96    
97    // Get cache statistics
98    let cache_hits = shared_state.conversations.counters.cache_hits.load(Ordering::Relaxed);
99    let cache_misses = shared_state.conversations.counters.cache_misses.load(Ordering::Relaxed);
100    let total_summaries = cache_hits + cache_misses; // Approximation
101    
102    // Get database file size from the database path
103    let database_size_bytes = match std::fs::metadata("data/conversations.db") {
104        Ok(metadata) => metadata.len(),
105        Err(_) => match std::fs::metadata("conversations.db") {
106            Ok(metadata) => metadata.len(),
107            Err(_) => 0,
108        }
109    };
110    
111    Ok((
112        StatusCode::OK,
113        Json(DbStatsResponse {
114            total_sessions,
115            total_messages,
116            total_summaries,
117            database_size_bytes,
118        }),
119    ))
120}
121
122/// Maintenance endpoint - performs system maintenance operations
123pub async fn maintenance(
124    State(shared_state): State<Arc<SharedState>>,
125    Json(payload): Json<MaintenanceRequest>,
126) -> Result<impl IntoResponse, StatusCode> {
127    match payload.operation.as_str() {
128        "cleanup_expired_sessions" => {
129            // Clear expired/inactive sessions from memory
130            // In a real implementation, we would remove sessions that haven't been accessed recently
131            let initial_count = shared_state.conversations.sessions.len();
132            
133            Ok((
134                StatusCode::OK,
135                Json(serde_json::json!({
136                    "message": "Expired sessions cleanup completed",
137                    "operation": "cleanup_expired_sessions",
138                    "initial_session_count": initial_count,
139                    "status": "completed"
140                })),
141            ))
142        },
143        "optimize_database" => {
144            // In a real implementation, we would perform database optimization
145            // For now, we'll just return a success message
146            Ok((
147                StatusCode::OK,
148                Json(serde_json::json!({
149                    "message": "Database optimization completed",
150                    "operation": "optimize_database",
151                    "status": "completed"
152                })),
153            ))
154        },
155        "clear_inactive_sessions" => {
156            // Clear inactive sessions from memory
157            let initial_count = shared_state.conversations.sessions.len();
158            
159            Ok((
160                StatusCode::OK,
161                Json(serde_json::json!({
162                    "message": "Inactive sessions cleared",
163                    "operation": "clear_inactive_sessions",
164                    "initial_session_count": initial_count,
165                    "status": "completed"
166                })),
167            ))
168        },
169        _ => {
170            Ok((
171                StatusCode::BAD_REQUEST,
172                Json(serde_json::json!({
173                    "message": format!("Unknown maintenance operation: {}", payload.operation),
174                    "supported_operations": ["cleanup_expired_sessions", "optimize_database", "clear_inactive_sessions"],
175                    "status": "error"
176                })),
177            ))
178        }
179    }
180}