From d332b7e91090916de2794ed782b5c2b962484227 Mon Sep 17 00:00:00 2001 From: jaakko Date: Mon, 6 Apr 2026 21:45:20 +0300 Subject: [PATCH] Hub priorisoi natiivisolmut (GPU) selainsolmujen edelle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lisätty node_types HashMap joka seuraa solmutyyppiä (native/browser). API reitittää tehtävät ensin vapaalle natiivisolmulle, sitten selaimelle. Co-Authored-By: Claude Opus 4.6 (1M context) --- network-poc/hub/src/main.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/network-poc/hub/src/main.rs b/network-poc/hub/src/main.rs index 1044e7d..22896f6 100644 --- a/network-poc/hub/src/main.rs +++ b/network-poc/hub/src/main.rs @@ -39,6 +39,7 @@ struct AppState { ip_connections: Mutex>, node_ips: Mutex>, node_tasks: Mutex>, // node_id → selected_task + node_types: Mutex>, // node_id → "native" | "browser" node_busy: Mutex>, // Solmut joilla on aktiivinen tehtävä pending_task_ids: Mutex>, // Hubin jakamat task_id:t (gamification-validointi) api_rate_limits: Mutex>, // IP → (ikkuna-alku, pyyntömäärä) @@ -260,6 +261,7 @@ async fn main() { ip_connections: Mutex::new(HashMap::new()), node_ips: Mutex::new(HashMap::new()), node_tasks: Mutex::new(HashMap::new()), + node_types: Mutex::new(HashMap::new()), node_busy: Mutex::new(std::collections::HashSet::new()), pending_task_ids: Mutex::new(std::collections::HashSet::new()), api_rate_limits: Mutex::new(HashMap::new()), @@ -677,6 +679,7 @@ async fn handle_socket(socket: WebSocket, state: Arc, ip: IpAddr) { state.db.insert_session(node_id, &ip.to_string(), node_type, &json); } state.node_tasks.lock().unwrap().insert(node_id, selected_task); + state.node_types.lock().unwrap().insert(node_id, node_type.to_string()); if node_type == "native" { let sys = json.get("system"); @@ -934,6 +937,7 @@ async fn handle_socket(socket: WebSocket, state: Arc, ip: IpAddr) { ips.remove(&node_id); vram.remove(&node_id); } + state.node_types.lock().unwrap().remove(&node_id); tracing::info!("Solmu {} ({}) poistui verkosta.", node_id, ip); broadcast_stats(&state).await; sender_task.abort(); @@ -972,10 +976,11 @@ async fn api_chat_completions( } } - // Etsitään vapaa tai varattu solmu, joka vastaa pyydettyä mallia + // Etsitään vapaa solmu — priorisoidaan natiivisolmut (GPU) selaimen edelle let (target_node_free, target_node_any, total_matching) = { let tasks = state.node_tasks.lock().unwrap(); let busy = state.node_busy.lock().unwrap(); + let node_types = state.node_types.lock().unwrap(); let matching: Vec = tasks.iter().filter(|(_, task)| { if payload.model == "qwen-coder" { task.starts_with("qwen-coder") @@ -983,7 +988,12 @@ async fn api_chat_completions( **task == payload.model } }).map(|(k, _)| *k).collect(); - let free = matching.iter().find(|id| !busy.contains(id)).copied(); + // Vapaat solmut: natiivi ensin, sitten selain + let free_native = matching.iter().find(|id| { + !busy.contains(id) && node_types.get(id).map(|t| t == "native").unwrap_or(false) + }).copied(); + let free_any = matching.iter().find(|id| !busy.contains(id)).copied(); + let free = free_native.or(free_any); let any = matching.first().copied(); (free, any, matching.len()) };