From 3cda57f0bcab24e984af0929c09ba8b38421bc2e Mon Sep 17 00:00:00 2001 From: Jaakko Vanhala Date: Sat, 11 Apr 2026 18:04:41 +0300 Subject: [PATCH] Hub: solmujen mallilistaus muistiin + /api/tags palauttaa verkon mallit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Natiivisolmun auth-viestistä tallennetaan mallilistaus node_models-mappiin. /api/tags priorisoi verkon solmujen malleja lokaalin Ollaman edelle. api_hardware käyttää tietokannan litteää rakennetta. Co-Authored-By: Claude Opus 4.6 (1M context) --- network-poc/hub/src/main.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/network-poc/hub/src/main.rs b/network-poc/hub/src/main.rs index 3ea6144..edd955c 100644 --- a/network-poc/hub/src/main.rs +++ b/network-poc/hub/src/main.rs @@ -44,6 +44,7 @@ struct AppState { pending_task_ids: Mutex>, // Hubin jakamat task_id:t (gamification-validointi) pending_responses: Mutex>>, // task_id → oneshot API-vastaukselle api_rate_limits: Mutex>, // IP → (ikkuna-alku, pyyntömäärä) + node_models: tokio::sync::RwLock>, // node_id → ollama tags JSON db: db::NodeDb, } @@ -303,6 +304,7 @@ async fn main() { pending_task_ids: Mutex::new(std::collections::HashSet::new()), pending_responses: Mutex::new(HashMap::new()), api_rate_limits: Mutex::new(HashMap::new()), + node_models: tokio::sync::RwLock::new(HashMap::new()), db: db::NodeDb::new(&std::env::var("DATABASE_PATH").unwrap_or_else(|_| "nodes.db".to_string())), }); @@ -781,6 +783,12 @@ async fn handle_socket(socket: WebSocket, state: Arc, ip: IpAddr) { node_id, ip, hostname, os, cores, ram, allocated ); + // Tallennetaan välitetyt mallit muistiin + if let Some(models) = json.get("models") { + let mut nm = state.node_models.write().await; + nm.insert(node_id, models.clone()); + } + if let Some(gpus) = json.get("gpus").and_then(|v| v.as_array()) { for gpu in gpus { tracing::info!( @@ -1045,6 +1053,7 @@ async fn handle_socket(socket: WebSocket, state: Arc, ip: IpAddr) { vram.remove(&node_id); } state.node_types.lock().unwrap().remove(&node_id); + state.node_models.write().await.remove(&node_id); tracing::info!("Solmu {} ({}) poistui verkosta.", node_id, ip); broadcast_stats(&state).await; sender_task.abort(); @@ -1065,7 +1074,16 @@ struct ChatCompletionResponse { tokens_generated: u64, } -async fn api_ollama_tags() -> axum::response::Response { +async fn api_ollama_tags( + axum::extract::State(state): axum::extract::State>, +) -> axum::response::Response { + // Haetaan natiivisolmun tila muistista — priorisoidaan aito verkko-solmu + let node_models = state.node_models.read().await; + if let Some((_, models_json)) = node_models.iter().next() { + return axum::Json(models_json.clone()).into_response(); + } + + // Fallback: Haetaan lokaalista infra-Ollamasta ohjaimesta käsin (esim dev ympäristö) let ollama_url = std::env::var("OLLAMA_URL").unwrap_or_else(|_| "http://ollama:11434".to_string()); match reqwest::get(format!("{}/api/tags", ollama_url)).await { Ok(resp) => { @@ -1089,11 +1107,10 @@ async fn api_hardware( }); let (mut vram_mb, mut gpu_name, ram_mb) = if let Some(s) = native { - let gpus = s.get("gpus").and_then(|v| v.as_array()); - let gpu = gpus.and_then(|g| g.first()); - let vram = gpu.and_then(|g| g.get("vram_total_mb")).and_then(|v| v.as_u64()).unwrap_or(0); - let name = gpu.and_then(|g| g.get("name")).and_then(|v| v.as_str()).unwrap_or("").to_string(); - let ram = s.get("system").and_then(|v| v.get("ram_total_mb")).and_then(|v| v.as_u64()).unwrap_or(0); + // Tieto on tietokannassa litteänä + let vram = s.get("vram_total_mb").and_then(|v| v.as_u64()).unwrap_or(0); + let name = s.get("gpu_name").and_then(|v| v.as_str()).unwrap_or("").to_string(); + let ram = s.get("ram_mb").and_then(|v| v.as_u64()).unwrap_or(0); (vram, name, ram) } else { (0, String::new(), 0)