zenith-runtime 0.1.0

Zenith 全链路数据面运行时:WorkerRuntime(eBPF + XSK + Worker 集成)、三级 Supervisor、ChangeSet 热切换、RuntimeGraph 拓扑规划
//! Zenith Runtime - 全链路数据面运行时
//!
//! 本 crate 提供 Zenith 数据面的核心运行时,包括:
//! - WorkerRuntime:eBPF + XSK + Worker 全链路集成
//! - RuntimeConfig:运行时配置
//! - RuntimeState:运行时状态机
//! - RuntimeStats:可观测性统计
//!
//! ## 模块结构
//! - [`runtime`] - WorkerRuntime 核心实现
//! - [`supervisor`] - 三级 Supervisor 层级(Node / Domain / Queue)
//! - [`changeset`] - ChangeSet 热切换状态机
//! - [`graph`] - RuntimeGraph 拓扑规划引擎
//!
//! ## 阻塞任务卸载
//! 阻塞任务统一委托 `tokio::task::spawn_blocking`(经 [`global`] 全局运行时分发),
//! 本 crate 不自建阻塞线程池(避免与 tokio 内置调度重复造轮子)。

#![deny(unsafe_code)]
#![deny(missing_debug_implementations)]
#![warn(missing_docs)]

pub mod auto_optimizer;
pub mod changeset;
#[cfg(target_os = "linux")]
pub mod cpu_affinity;
#[cfg(not(target_os = "linux"))]
#[path = "cpu_affinity_stub.rs"]
pub mod cpu_affinity;
pub mod extreme_planner;
pub mod global;
pub mod graph;
pub mod runtime;
pub mod supervisor;
pub mod task_channel;

pub use auto_optimizer::{
    AdaptiveQos, AutoOptimizer, CacheAccessPattern, CacheWarmupPredictor, LoadHistory,
    LoadSample, LoadTrend, QosLevel,
};
pub use cpu_affinity::{AffinityManager, CpuAffinityConfig, CpuAffinityError, CpuId};
pub use extreme_planner::ExtremePlanner;
pub use global::{block_on, global_runtime, handle, init_global, spawn, BlockOnError, GlobalRuntime};
pub use graph::{
    AffinityRule, DomainAssignment, DomainSnapshot, ExecutionDomain, GraphError,
    NodeStatus, PlannedTopology, QueueDistribution, QueueMapping, QueueStrategy,
    ResourceNode, RuntimeGraph, TopologyPlanner, WorkerAssignment,
};
pub use supervisor::{
    BackoffConfig, ChildEntry, ChildKind, ChildSet, DomainSupervisor, ExitReason, HealthReport,
    NodeSupervisor, QueueSupervisor, RestartStrategy, SupervisorConfig, SupervisorCore,
    SupervisorError, SupervisorState,
};
pub use task_channel::{
    TaskError, TaskOffloadChannel, TaskOutput, TaskPayload, TaskRequest, TaskResult,
};

/// 运行时配置
#[derive(Debug, Clone, Copy)]
pub struct RuntimeConfig {
    /// 工作线程数
    pub worker_threads: usize,
    /// 是否启用 IO 驱动
    pub enable_io: bool,
    /// 是否启用时间驱动器
    pub enable_time: bool,
    /// 栈大小(字节)
    pub stack_size: usize,
}

impl RuntimeConfig {
    /// 创建新的运行时配置
    pub fn new() -> Self {
        Self {
            worker_threads: num_cpus(),
            enable_io: true,
            enable_time: true,
            stack_size: 2 * 1024 * 1024,
        }
    }

    /// 设置工作线程数
    ///
    /// # Arguments
    /// * `n` - 线程数
    pub fn with_worker_threads(mut self, n: usize) -> Self {
        self.worker_threads = n;
        self
    }

    /// 设置栈大小
    ///
    /// # Arguments
    /// * `size` - 栈大小字节数
    pub fn with_stack_size(mut self, size: usize) -> Self {
        self.stack_size = size;
        self
    }
}

impl Default for RuntimeConfig {
    fn default() -> Self {
        Self::new()
    }
}

/// 获取 CPU 核心数
///
/// # Returns
/// * `usize` - CPU 核心数
fn num_cpus() -> usize {
    std::thread::available_parallelism()
        .map(|n| n.get())
        .unwrap_or(4)
}

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

    #[test]
    fn test_runtime_config_default() {
        let config = RuntimeConfig::new();
        assert!(config.worker_threads >= 1);
        assert!(config.enable_io);
        assert!(config.enable_time);
        assert_eq!(config.stack_size, 2 * 1024 * 1024);
    }

    #[test]
    fn test_runtime_config_custom() {
        let config = RuntimeConfig::new()
            .with_worker_threads(8)
            .with_stack_size(4 * 1024 * 1024);
        assert_eq!(config.worker_threads, 8);
        assert_eq!(config.stack_size, 4 * 1024 * 1024);
    }

    #[test]
    fn test_num_cpus() {
        let cpus = num_cpus();
        assert!(cpus >= 1);
    }

    #[test]
    fn test_runtime_config_debug() {
        let config = RuntimeConfig::new();
        let debug_str = format!("{:?}", config);
        assert!(!debug_str.is_empty());
        assert!(debug_str.contains("RuntimeConfig"));
    }

    #[test]
    fn test_runtime_config_clone() {
        let config = RuntimeConfig::new().with_worker_threads(4);
        let cloned = config;
        assert_eq!(config.worker_threads, cloned.worker_threads);
        assert_eq!(config.stack_size, cloned.stack_size);
    }

    #[test]
    fn test_runtime_config_default_trait() {
        let config: RuntimeConfig = Default::default();
        assert!(config.worker_threads >= 1);
    }

    #[test]
    fn test_with_worker_threads_zero() {
        let config = RuntimeConfig::new().with_worker_threads(0);
        assert_eq!(config.worker_threads, 0);
    }

    #[test]
    fn test_with_stack_size_small() {
        let config = RuntimeConfig::new().with_stack_size(4096);
        assert_eq!(config.stack_size, 4096);
    }

    #[test]
    fn test_runtime_config_enable_flags() {
        let mut config = RuntimeConfig::new();
        config.enable_io = false;
        config.enable_time = false;
        assert!(!config.enable_io);
        assert!(!config.enable_time);
    }
}