Reititys: busy-solmut suodatetaan pois — työ jakautuu solmuille

Aiemmin busy-lukko luettiin mutta sitä ei käytetty suodatukseen,
joten sama solmu valittiin aina uudelleen vaikka se oli varattu.
Nyt matching-lista suodattaa pois busy-solmut, joten toinen
vapaa solmu saa tehtävän. Heavy-fallback kevyempään solmuun
jos kaikki isot mallit ovat varattuja.
This commit is contained in:
2026-04-13 21:09:24 +03:00
parent e09962940a
commit 763b93396c

View File

@@ -1314,12 +1314,12 @@ async fn api_chat_completions(
let param_b_snapshot: HashMap<u64, u32> = state.node_max_param_b.read().await.clone(); let param_b_snapshot: HashMap<u64, u32> = state.node_max_param_b.read().await.clone();
let (target_node, _total_matching) = { let (target_node, _total_matching) = {
let tasks = state.node_tasks.lock().unwrap(); let tasks = state.node_tasks.lock().unwrap();
let _busy = state.node_busy.lock().unwrap(); let busy = state.node_busy.lock().unwrap();
let node_types = state.node_types.lock().unwrap(); let node_types = state.node_types.lock().unwrap();
let paused = state.node_paused.lock().unwrap(); let paused = state.node_paused.lock().unwrap();
let matching: Vec<u64> = tasks.iter().filter(|(k, task)| { let matching: Vec<u64> = tasks.iter().filter(|(k, task)| {
if paused.contains(k) { return false; } // Ei sallita tauotettuja if paused.contains(k) { return false; } // Ei tauotettuja
// Eksakti match tai qwen-perheen yhteensopivuus (selain: qwen-coder-05b, natiivi: qwen2.5-coder:7b) if busy.contains(k) { return false; } // Ei varattuja
let req_model = payload.model.to_lowercase(); let req_model = payload.model.to_lowercase();
let node_task = task.to_lowercase(); let node_task = task.to_lowercase();
if req_model.starts_with("qwen") { if req_model.starts_with("qwen") {
@@ -1341,10 +1341,16 @@ async fn api_chat_completions(
tracing::info!("Heavy-reititys: solmu {} valittu ({}B parametria)", best_id, best_b); tracing::info!("Heavy-reititys: solmu {} valittu ({}B parametria)", best_id, best_b);
Some(*best_id) Some(*best_id)
} else { } else {
None // Kaikki heavy-solmut busy — fallback mihin tahansa vapaaseen
let all_matching: Vec<u64> = tasks.iter().filter(|(k, task)| {
if paused.contains(k) || busy.contains(k) { return false; }
let req_model = payload.model.to_lowercase();
task.to_lowercase().starts_with(&req_model.split('-').next().unwrap_or(""))
}).map(|(k, _)| *k).collect();
all_matching.first().copied()
} }
} else { } else {
// Oletus: natiivi ensin, sitten mikä tahansa // Oletus: vapaa natiivi ensin, sitten mikä tahansa vapaa
let native = matching.iter().find(|id| { let native = matching.iter().find(|id| {
node_types.get(id).map(|t| t == "native").unwrap_or(false) node_types.get(id).map(|t| t == "native").unwrap_or(false)
}).copied(); }).copied();