Hub priorisoi natiivisolmut (GPU) selainsolmujen edelle

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) <noreply@anthropic.com>
This commit is contained in:
2026-04-06 21:45:20 +03:00
parent 8e55a15d66
commit d332b7e910

View File

@@ -39,6 +39,7 @@ struct AppState {
ip_connections: Mutex<HashMap<IpAddr, u32>>,
node_ips: Mutex<HashMap<u64, IpAddr>>,
node_tasks: Mutex<HashMap<u64, String>>, // node_id → selected_task
node_types: Mutex<HashMap<u64, String>>, // node_id → "native" | "browser"
node_busy: Mutex<std::collections::HashSet<u64>>, // Solmut joilla on aktiivinen tehtävä
pending_task_ids: Mutex<std::collections::HashSet<String>>, // Hubin jakamat task_id:t (gamification-validointi)
api_rate_limits: Mutex<HashMap<IpAddr, (std::time::Instant, u32)>>, // 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<AppState>, 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<AppState>, 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<u64> = 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())
};