nexus-gateway 0.0.1-alpha

S3-compatible object gateway and embedded Nexus console.
use nexus_core::topology::{CpuGeneration, TopologyReport};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RuntimeProfile {
    Auto,
    Epyc,
    Dev,
}

impl RuntimeProfile {
    pub fn from_str(value: &str) -> anyhow::Result<Self> {
        match value {
            "auto" => Ok(Self::Auto),
            "epyc" => Ok(Self::Epyc),
            "dev" => Ok(Self::Dev),
            other => anyhow::bail!("unsupported runtime profile: {other}"),
        }
    }

    pub fn resolve(self) -> Self {
        match self {
            Self::Auto => {
                if cfg!(target_arch = "aarch64") {
                    Self::Dev
                } else {
                    Self::Epyc
                }
            }
            other => other,
        }
    }

    pub fn as_str(self) -> &'static str {
        match self {
            Self::Auto => "auto",
            Self::Epyc => "epyc",
            Self::Dev => "dev",
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AtcForceMode {
    Auto,
    Hypervisor,
    Posix,
}

impl AtcForceMode {
    pub fn from_str(value: &str) -> anyhow::Result<Self> {
        match value {
            "auto" => Ok(Self::Auto),
            "hypervisor" => Ok(Self::Hypervisor),
            "posix" => Ok(Self::Posix),
            other => anyhow::bail!("unsupported ATC force mode: {other}"),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AtcMode {
    Hypervisor,
    Posix,
}

impl AtcMode {
    pub fn as_str(self) -> &'static str {
        match self {
            Self::Hypervisor => "hypervisor",
            Self::Posix => "posix",
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WorkerModel {
    PinnedLocalset,
    TokioWorkStealing,
}

impl WorkerModel {
    pub fn as_str(self) -> &'static str {
        match self {
            Self::PinnedLocalset => "pinned-localset",
            Self::TokioWorkStealing => "tokio-workstealing",
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IoModel {
    DirectSync,
    Buffered,
}

impl IoModel {
    pub fn as_str(self) -> &'static str {
        match self {
            Self::DirectSync => "direct-sync",
            Self::Buffered => "buffered",
        }
    }
}

#[derive(Debug, Clone)]
pub struct AtcDecision {
    pub mode: AtcMode,
    pub runtime_profile: RuntimeProfile,
    pub device_count: usize,
    pub cpu_generation: CpuGeneration,
    pub numa_nodes: usize,
    pub worker_model: WorkerModel,
    pub io_model: IoModel,
    pub reason: String,
}

impl AtcDecision {
    pub fn to_json(&self) -> String {
        format!(
            "{{\"mode\":\"{}\",\"runtime_profile\":\"{}\",\"device_count\":{},\"cpu_generation\":\"{}\",\"numa_nodes\":{},\"worker_model\":\"{}\",\"io_model\":\"{}\",\"reason\":\"{}\"}}",
            self.mode.as_str(),
            self.runtime_profile.as_str(),
            self.device_count,
            cpu_generation_label(self.cpu_generation),
            self.numa_nodes,
            self.worker_model.as_str(),
            self.io_model.as_str(),
            json_escape(self.reason.as_str()),
        )
    }
}

#[derive(Debug)]
pub struct AtcInput<'a> {
    pub runtime_profile: RuntimeProfile,
    pub force_mode: AtcForceMode,
    pub device_count: usize,
    pub single_device_threshold: usize,
    pub topology: &'a TopologyReport,
}

pub fn decide(input: AtcInput<'_>) -> AtcDecision {
    let runtime_profile = input.runtime_profile.resolve();
    let single_threshold = input.single_device_threshold.max(1);
    let device_count = input.device_count.max(1);
    let is_single_device = device_count <= single_threshold;
    let is_amd_zen = input.topology.cpu_vendor == "AuthenticAMD"
        && matches!(
            input.topology.cpu_generation,
            CpuGeneration::Zen2 | CpuGeneration::Zen3
        );
    let has_numa_or_ccx =
        input.topology.numa_nodes.len() > 1 || !input.topology.ccx_groups.is_empty();

    let (mode, reason) = match input.force_mode {
        AtcForceMode::Hypervisor => (
            AtcMode::Hypervisor,
            "forced ATC mode hypervisor via --atc-force-mode".to_string(),
        ),
        AtcForceMode::Posix => (
            AtcMode::Posix,
            "forced ATC mode posix via --atc-force-mode".to_string(),
        ),
        AtcForceMode::Auto => {
            if runtime_profile == RuntimeProfile::Dev {
                (
                    AtcMode::Posix,
                    "runtime profile resolved to dev".to_string(),
                )
            } else if is_single_device {
                (
                    AtcMode::Posix,
                    format!(
                        "device_count={} <= atc_single_device_threshold={}",
                        device_count, single_threshold
                    ),
                )
            } else if is_amd_zen && has_numa_or_ccx {
                (
                    AtcMode::Hypervisor,
                    "multi-device EPYC/Zen topology detected".to_string(),
                )
            } else {
                (
                    AtcMode::Posix,
                    "topology not classified as EPYC/NUMA multi-device target".to_string(),
                )
            }
        }
    };

    let (worker_model, io_model) = match mode {
        AtcMode::Hypervisor => (WorkerModel::PinnedLocalset, IoModel::DirectSync),
        AtcMode::Posix => (WorkerModel::TokioWorkStealing, IoModel::Buffered),
    };

    AtcDecision {
        mode,
        runtime_profile,
        device_count,
        cpu_generation: input.topology.cpu_generation,
        numa_nodes: input.topology.numa_nodes.len(),
        worker_model,
        io_model,
        reason,
    }
}

fn cpu_generation_label(value: CpuGeneration) -> &'static str {
    match value {
        CpuGeneration::Zen2 => "Zen2",
        CpuGeneration::Zen3 => "Zen3",
        CpuGeneration::Unknown => "Unknown",
    }
}

fn json_escape(value: &str) -> String {
    value
        .chars()
        .flat_map(|ch| match ch {
            '\\' => "\\\\".chars().collect::<Vec<_>>(),
            '"' => "\\\"".chars().collect::<Vec<_>>(),
            '\n' => "\\n".chars().collect::<Vec<_>>(),
            '\r' => "\\r".chars().collect::<Vec<_>>(),
            '\t' => "\\t".chars().collect::<Vec<_>>(),
            other => vec![other],
        })
        .collect()
}

#[cfg(test)]
mod tests {
    use super::*;
    use nexus_core::topology::RssIrqAffinity;

    fn topology(cpu_generation: CpuGeneration, cpu_vendor: &str, numa_nodes: usize) -> TopologyReport {
        TopologyReport {
            cpu_vendor: cpu_vendor.to_string(),
            family_model: "0x19:0x1".to_string(),
            cpu_generation,
            numa_nodes: (0..numa_nodes).map(|_| vec![0, 1]).collect(),
            ccx_groups: vec![vec![0, 1, 2, 3]],
            rss_irq_map: vec![RssIrqAffinity {
                irq: 1,
                cpus: vec![0, 1],
            }],
            selected_cores: vec![0, 1, 2, 3],
        }
    }

    #[test]
    fn auto_chooses_posix_for_single_device() {
        let t = topology(CpuGeneration::Zen3, "AuthenticAMD", 2);
        let decision = decide(AtcInput {
            runtime_profile: RuntimeProfile::Auto,
            force_mode: AtcForceMode::Auto,
            device_count: 1,
            single_device_threshold: 1,
            topology: &t,
        });
        assert_eq!(decision.mode, AtcMode::Posix);
        assert_eq!(decision.io_model, IoModel::Buffered);
    }

    #[test]
    fn auto_chooses_hypervisor_for_multi_device_epyc() {
        let t = topology(CpuGeneration::Zen3, "AuthenticAMD", 2);
        let decision = decide(AtcInput {
            runtime_profile: RuntimeProfile::Epyc,
            force_mode: AtcForceMode::Auto,
            device_count: 5,
            single_device_threshold: 1,
            topology: &t,
        });
        assert_eq!(decision.mode, AtcMode::Hypervisor);
        assert_eq!(decision.worker_model, WorkerModel::PinnedLocalset);
    }

    #[test]
    fn force_mode_overrides_auto_logic() {
        let t = topology(CpuGeneration::Unknown, "GenuineIntel", 1);
        let decision = decide(AtcInput {
            runtime_profile: RuntimeProfile::Auto,
            force_mode: AtcForceMode::Hypervisor,
            device_count: 1,
            single_device_threshold: 1,
            topology: &t,
        });
        assert_eq!(decision.mode, AtcMode::Hypervisor);
        assert_eq!(decision.io_model, IoModel::DirectSync);
    }
}