righvalor 0.1.0

RighValor: AI Infrastructure and Applications Framework for the Far Edge
use crate::{
    common::task::ValorMasterTask, master::ValorWorkerRegistry, service::ValorServiceId,
    types::ValorID,
};

/// Minimal, service-aware scheduler
///
/// Strategy:
/// - prefer READY workers that advertise the requested `service_id`
/// - tie-break by larger `free_cpu`
/// - fallback: any READY worker
pub struct ValorMasterScheduler;

impl ValorMasterScheduler {
    pub fn select_worker(task: &ValorMasterTask, reg: &ValorWorkerRegistry) -> Option<ValorID> {
        // Extract required service_id from task
        let required: Option<ValorServiceId> = match &task.task_type {
            crate::common::task::ValorTaskType::ExecuteService { service_id, .. } => {
                Some(service_id.clone())
            }
        };

        // 1) service-aware pass
        if let Some(req) = required {
            let mut best: Option<(ValorID, u32)> = None;
            for (id, rec) in reg.iter() {
                if rec.state == crate::master::ValorWorkerState::Ready
                    && rec.services.iter().any(|s| s == &req)
                {
                    let score = rec.capacity.free_cpu;
                    if best.as_ref().map(|b| score > b.1).unwrap_or(true) {
                        best = Some((id.clone(), score));
                    }
                }
            }
            if let Some((id, _)) = best {
                return Some(id);
            }
        }

        // 2) fallback: any READY worker, max free_cpu
        let mut best: Option<(ValorID, u32)> = None;
        for (id, rec) in reg.iter() {
            if rec.state == crate::master::ValorWorkerState::Ready {
                let score = rec.capacity.free_cpu;
                if best.as_ref().map(|b| score > b.1).unwrap_or(true) {
                    best = Some((id.clone(), score));
                }
            }
        }

        best.map(|(id, _)| id)
    }
}