use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex, RwLock};
use tracing::{error, info, warn};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::SystemTime;
pub struct RuntimeConfigManager {
config: Arc<RwLock<RuntimeConfig>>,
config_path: Option<String>,
auto_tuner: Option<Arc<AutoTuner>>,
change_callbacks: Arc<RwLock<Vec<ConfigChangeCallback>>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuntimeConfig {
pub runtime: RuntimeConfigSection,
pub v8: V8ConfigSection,
pub memory: MemoryConfigSection,
pub performance: PerformanceConfigSection,
pub monitoring: MonitoringConfigSection,
pub logging: LoggingConfigSection,
pub security: SecurityConfigSection,
pub network: NetworkConfigSection,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuntimeConfigSection {
pub environment: String,
pub instance_id: String,
pub startup_time_ms: u64,
pub version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct V8ConfigSection {
pub max_heap_size_mb: usize,
pub initial_heap_size_mb: usize,
pub enable_jit: bool,
pub jit_optimization_level: u8,
pub concurrent_marking: bool,
pub incremental_marking: bool,
pub concurrent_sweeping: bool,
pub code_cache_size_mb: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryConfigSection {
pub pool_size_mb: usize,
pub enable_zero_copy: bool,
pub enable_compression: bool,
pub leak_detection_interval_s: u64,
pub leak_threshold_mb: usize,
pub gc_tuning: GCTuningConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GCTuningConfig {
pub trigger_threshold_percent: f64,
pub target_pause_time_ms: u64,
pub enable_incremental_gc: bool,
pub enable_parallel_gc: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default)]
pub struct PerformanceConfigSection {
pub enable_profiling: bool,
pub profiling_sample_interval_ms: u64,
pub max_concurrent_tasks: usize,
pub work_stealing_queue_size: usize,
pub enable_fast_path: bool,
pub cpu_affinity: Option<Vec<usize>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default)]
pub struct MonitoringConfigSection {
pub enable_prometheus: bool,
pub prometheus_addr: String,
pub monitoring_interval_s: u64,
pub enable_intelligent_analysis: bool,
pub enable_auto_tuning: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default)]
pub struct LoggingConfigSection {
pub log_level: String,
pub enable_structured_logging: bool,
pub log_file: Option<String>,
pub max_log_file_size_mb: usize,
pub log_rotation_count: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default)]
pub struct SecurityConfigSection {
pub enable_sandbox: bool,
pub resource_limit_mb: usize,
pub max_execution_time_s: u64,
pub disable_dangerous_functions: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkConfigSection {
pub http_port: u16,
pub websocket_port: u16,
pub max_connections: usize,
pub connection_timeout_s: u64,
}
pub type ConfigChangeCallback = Box<dyn Fn(&str, &serde_json::Value) + Send + Sync>;
pub struct AutoTuner {
config_manager: Arc<RuntimeConfigManager>,
is_tuning: bool,
tuning_interval_s: u64,
metrics_collector: Arc<PerformanceMetricsCollector>,
}
pub struct PerformanceMetricsCollector {
execution_times: Arc<RwLock<Vec<u64>>>,
memory_usage: Arc<RwLock<Vec<usize>>>,
cpu_usage: Arc<RwLock<Vec<f64>>>,
}
impl AutoTuner {
pub fn new(config_manager: Arc<RuntimeConfigManager>, tuning_interval_s: u64) -> Self {
Self {
config_manager,
is_tuning: false,
tuning_interval_s,
metrics_collector: Arc::new(Mutex::new(PerformanceMetricsCollector::new())),
}
}
pub async fn start(&self) -> Result<(), Box<dyn std::error::Error>> {
if self.is_tuning {
warn!("自动调优已经在运行中");
return Ok(());
}
info!("启动自动调优器,间隔: {} 秒", self.tuning_interval_s);
Ok(())
}
pub async fn stop(&self) -> Result<(), Box<dyn std::error::Error>> {
info!("停止自动调优器");
Ok(())
}
pub async fn tune(&self) -> Result<TuningResult, Box<dyn std::error::Error>> {
info!("开始手动调优");
let config: _ = self.config_manager.get_config().await;
let mut tuned_config = config.clone();
let mut changes = Vec::new();
if self.should_adjust_v8_config() {
if let Ok(new_max_heap) = self.calculate_optimal_heap_size().await {
tuned_config.v8.max_heap_size_mb = new_max_heap;
changes.push(format!("调整 V8 最大堆大小: {} MB", new_max_heap));
}
}
if self.should_adjust_memory_config() {
if let Ok(new_pool_size) = self.calculate_optimal_pool_size().await {
tuned_config.memory.pool_size_mb = new_pool_size;
changes.push(format!("调整内存池大小: {} MB", new_pool_size));
}
}
if self.should_adjust_concurrent_config() {
if let Ok(new_max_tasks) = self.calculate_optimal_concurrent_tasks().await {
tuned_config.performance.max_concurrent_tasks = new_max_tasks;
changes.push(format!("调整最大并发任务数: {}", new_max_tasks));
}
}
if !changes.is_empty() {
*self.config_manager.config.write().await = tuned_config;
}
Ok(TuningResult {
applied_changes: changes.len(),
changes,
timestamp: std::time::SystemTime::now(),
})
}
fn should_adjust_v8_config(&self) -> bool {
true
}
async fn calculate_optimal_heap_size(&self) -> Result<usize, Box<dyn std::error::Error>> {
let memory_usage: _ = self.metrics_collector.get_average_memory_usage().await?;
let current_config: _ = self.config_manager.get_config().await;
let optimal_size: _ = if memory_usage > 200 { 512 } else { 256 };
Ok(optimal_size)
}
fn should_adjust_memory_config(&self) -> bool {
true
}
async fn calculate_optimal_pool_size(&self) -> Result<usize, Box<dyn std::error::Error>> {
let execution_times: _ = self.metrics_collector.get_average_execution_time().await?;
let current_config: _ = self.config_manager.get_config().await;
let optimal_size: _ = if execution_times > 100 { 256 } else { 128 };
Ok(optimal_size)
}
fn should_adjust_concurrent_config(&self) -> bool {
true
}
async fn calculate_optimal_concurrent_tasks(&self) -> Result<usize, Box<dyn std::error::Error>> {
let cpu_usage: _ = self.metrics_collector.get_average_cpu_usage().await?;
let current_config: _ = self.config_manager.get_config().await;
let optimal_tasks: _ = if cpu_usage > 0.8 { 500 } else { 1000 };
Ok(optimal_tasks)
}
}
pub struct TuningResult {
pub applied_changes: usize,
pub changes: Vec<String>,
pub timestamp: std::time::SystemTime,
}
impl PerformanceMetricsCollector {
pub fn new() -> Self {
Self {
execution_times: Arc::new(Mutex::new(Vec::new())),
memory_usage: Arc::new(Mutex::new(Vec::new())),
cpu_usage: Arc::new(Mutex::new(Vec::new())),
}
}
pub async fn record_execution_time(&self, time_ms: u64) {
let mut times = self.execution_times.write().await;
times.push(time_ms);
if times.len() > 1000 {
times.remove(0);
}
}
pub async fn record_memory_usage(&self, usage_mb: usize) {
let mut usage = self.memory_usage.write().await;
usage.push(usage_mb);
if usage.len() > 1000 {
usage.remove(0);
}
}
pub async fn record_cpu_usage(&self, usage: f64) {
let mut usage_list = self.cpu_usage.write().await;
usage_list.push(usage);
if usage_list.len() > 1000 {
usage_list.remove(0);
}
}
pub async fn get_average_execution_time(&self) -> Result<u64, Box<dyn std::error::Error>> {
let times: _ = self.execution_times.read().await;
if times.is_empty() {
return Ok(0);
}
let sum: u64 = times.iter().sum();
Ok(sum / times.len() as u64)
}
pub async fn get_average_memory_usage(&self) -> Result<usize, Box<dyn std::error::Error>> {
let usage: _ = self.memory_usage.read().await;
if usage.is_empty() {
return Ok(0);
}
let sum: usize = usage.iter().sum();
Ok(sum / usage.len())
}
pub async fn get_average_cpu_usage(&self) -> Result<f64, Box<dyn std::error::Error>> {
let usage: _ = self.cpu_usage.read().await;
if usage.is_empty() {
return Ok(0.0);
}
let sum: f64 = usage.iter().sum();
Ok(sum / usage.len() as f64)
}
}
impl Default for PerformanceMetricsCollector {
fn default() -> Self {
Self::new()
}
}
impl RuntimeConfigManager {
pub fn new() -> Self {
let config: _ = RuntimeConfig::default();
Self {
config: Arc::new(Mutex::new(config)),
config_path: None,
auto_tuner: None,
change_callbacks: Arc::new(Mutex::new(Vec::new())),
}
}
pub async fn load_from_file(&mut self, path: &str) -> Result<(), Box<dyn std::error::Error>> {
info!("加载配置文件: {}", path);
let config_str: _ = fs::read_to_string(path)?;
let config: RuntimeConfig = serde_json::from_str(&config_str)?;
*self.config.write().await = config;
self.config_path = Some(path.to_string());
info!("配置文件加载成功");
Ok(())
}
pub async fn save_to_file(&self) -> Result<(), Box<dyn std::error::Error>> {
if let Some(path) = &self.config_path {
let config: _ = self.config.read().await;
let config_str: _ = serde_json::to_string_pretty(&*config)?;
fs::write(path, config_str)?;
info!("配置文件已保存: {}", path);
Ok(())
} else {
Err("未设置配置文件路径".into())
}
}
pub async fn get_config_snapshot(&self) -> ConfigSnapshot {
let config: _ = self.config.read().await;
ConfigSnapshot {
config: config.clone(),
timestamp: std::time::SystemTime::now(),
}
}
pub async fn get_config(&self) -> RuntimeConfig {
self.config.read().await.clone()
}
pub async fn update_config<F>(&self, update_fn: F) -> Result<(), Box<dyn std::error::Error>>
where
F: FnOnce(&mut RuntimeConfig),
{
let mut config = self.config.write().await;
update_fn(&mut config);
let callbacks: _ = self.change_callbacks.read().await;
let config_value: _ = serde_json::to_value(&*config)?;
for callback in callbacks.iter() {
callback("runtime_config", &config_value);
}
Ok(())
}
pub async fn update_config_value<T>(
&self,
path: &str,
value: T,
) -> Result<(), Box<dyn std::error::Error>>
where
T: Serialize + for<'de> Deserialize<'de> + Clone,
{
let mut config = self.config.write().await;
let value_json: _ = serde_json::to_value(value)?;
let parts: Vec<&str> = path.split('.').collect();
if parts.len() >= 2 {
match parts[0] {
"runtime" => {
let section_json: _ = serde_json::to_value(&config.runtime)?;
if let Ok(updated) = self.update_json_field(section_json, &parts[1..], value_json) {
config.runtime = serde_json::from_value(updated)?;
}
}
"v8" => {
let section_json: _ = serde_json::to_value(&config.v8)?;
if let Ok(updated) = self.update_json_field(section_json, &parts[1..], value_json) {
config.v8 = serde_json::from_value(updated)?;
}
}
"memory" => {
let section_json: _ = serde_json::to_value(&config.memory)?;
if let Ok(updated) = self.update_json_field(section_json, &parts[1..], value_json) {
config.memory = serde_json::from_value(updated)?;
}
}
"performance" => {
let section_json: _ = serde_json::to_value(&config.performance)?;
if let Ok(updated) = self.update_json_field(section_json, &parts[1..], value_json) {
config.performance = serde_json::from_value(updated)?;
}
}
"monitoring" => {
let section_json: _ = serde_json::to_value(&config.monitoring)?;
if let Ok(updated) = self.update_json_field(section_json, &parts[1..], value_json) {
config.monitoring = serde_json::from_value(updated)?;
}
}
"logging" => {
let section_json: _ = serde_json::to_value(&config.logging)?;
if let Ok(updated) = self.update_json_field(section_json, &parts[1..], value_json) {
config.logging = serde_json::from_value(updated)?;
}
}
"security" => {
let section_json: _ = serde_json::to_value(&config.security)?;
if let Ok(updated) = self.update_json_field(section_json, &parts[1..], value_json) {
config.security = serde_json::from_value(updated)?;
}
}
"network" => {
let section_json: _ = serde_json::to_value(&config.network)?;
if let Ok(updated) = self.update_json_field(section_json, &parts[1..], value_json) {
config.network = serde_json::from_value(updated)?;
}
}
_ => return Err(format!("未知的配置节: {}", parts[0]).into()),
}
}
Ok(())
}
fn update_json_field(
&self,
mut section_json: serde_json::Value,
field_parts: &[&str],
value_json: serde_json::Value,
) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
if field_parts.len() == 1 {
if let serde_json::Value::Object(ref mut map) = section_json {
map.insert(field_parts[0].to_string(), value_json);
Ok(section_json)
} else {
Err("配置节必须是对象类型".into())
}
} else {
Ok(value_json)
}
}
pub async fn add_change_callback(&self, callback: ConfigChangeCallback) {
let mut callbacks = self.change_callbacks.write().await;
callbacks.push(callback);
}
pub fn enable_auto_tuning(&mut self) {
info!("启用配置自动调优");
self.auto_tuner = Some(Arc::new(Mutex::new(AutoTuner::new(
Arc::new(self.clone()),
60,
))));
}
pub async fn enable_hot_reload(&mut self) -> Result<(), Box<dyn std::error::Error>> {
if let Some(ref config_path) = self.config_path {
info!("启用配置热更新,监听文件: {}", config_path);
Ok(())
} else {
Err("未设置配置文件路径,无法启用热更新".into())
}
}
pub async fn load_from_env(&mut self) -> Result<(), Box<dyn std::error::Error>> {
info!("从环境变量加载配置");
let mut config = RuntimeConfig::default();
if let Ok(env) = std::env::var("AMBER_ENVIRONMENT") {
config.runtime.environment = env;
}
if let Ok(heap_size) = std::env::var("AMBER_V8_MAX_HEAP_SIZE") {
if let Ok(size) = heap_size.parse::<usize>() {
config.v8.max_heap_size_mb = size;
}
}
if let Ok(pool_size) = std::env::var("AMBER_MEMORY_POOL_SIZE") {
if let Ok(size) = pool_size.parse::<usize>() {
config.memory.pool_size_mb = size;
}
}
if let Ok(log_level) = std::env::var("AMBER_LOG_LEVEL") {
config.logging.log_level = log_level;
}
*self.config.write().await = config;
info!("从环境变量加载配置完成");
Ok(())
}
pub async fn adapt_for_environment(&mut self) -> Result<(), Box<dyn std::error::Error>> {
let config: _ = self.config.read().await;
let environment: _ = config.runtime.environment.clone();
match environment.as_str() {
"development" => {
drop(config);
self.update_config(|c| {
c.logging.log_level = "debug".to_string();
c.security.resource_limit_mb = 1024;
c.performance.max_concurrent_tasks = 100;
}).await?;
}
"testing" => {
drop(config);
self.update_config(|c| {
c.logging.log_level = "warn".to_string();
c.monitoring.enable_prometheus = false;
c.performance.enable_profiling = false;
}).await?;
}
"production" => {
drop(config);
self.update_config(|c| {
c.logging.log_level = "info".to_string();
c.monitoring.enable_prometheus = true;
c.security.enable_sandbox = true;
c.performance.enable_profiling = true;
}).await?;
}
_ => {
warn!("未知环境: {},使用默认配置", environment);
}
}
info!("已为环境 '{}' 调整配置", environment);
Ok(())
}
pub fn get_defaults_for_environment(env: &str) -> RuntimeConfig {
match env {
"development" => RuntimeConfig {
logging: LoggingConfigSection {
log_level: "debug".to_string(),
..Default::default()
},
..Default::default()
},
"testing" => RuntimeConfig {
monitoring: MonitoringConfigSection {
enable_prometheus: false,
..Default::default()
},
performance: PerformanceConfigSection {
enable_profiling: false,
..Default::default()
},
..Default::default()
},
"production" => RuntimeConfig {
security: SecurityConfigSection {
enable_sandbox: true,
resource_limit_mb: 2048,
..Default::default()
},
monitoring: MonitoringConfigSection {
enable_prometheus: true,
enable_intelligent_analysis: true,
..Default::default()
},
..Default::default()
},
_ => RuntimeConfig::default(),
}
}
pub async fn validate_config(&self) -> Result<(), Box<dyn std::error::Error>> {
let config: _ = self.config.read().await;
let mut errors = Vec::new();
if config.v8.max_heap_size_mb < config.v8.initial_heap_size_mb {
errors.push("最大堆大小不能小于初始堆大小".to_string());
}
if config.v8.max_heap_size_mb == 0 {
errors.push("最大堆大小必须大于 0".to_string());
}
if config.v8.jit_optimization_level > 4 {
errors.push("JIT 优化级别不能超过 4".to_string());
}
if config.v8.code_cache_size_mb > config.v8.max_heap_size_mb {
errors.push("代码缓存大小不能大于最大堆大小".to_string());
}
if config.memory.pool_size_mb == 0 {
errors.push("内存池大小必须大于 0".to_string());
}
if config.memory.leak_threshold_mb > config.memory.pool_size_mb {
errors.push("泄漏阈值不能大于内存池大小".to_string());
}
if config.memory.gc_tuning.trigger_threshold_percent < 0.0
|| config.memory.gc_tuning.trigger_threshold_percent > 100.0 {
errors.push("GC 触发阈值必须在 0-100% 之间".to_string());
}
if config.memory.gc_tuning.target_pause_time_ms == 0 {
errors.push("GC 目标暂停时间必须大于 0".to_string());
}
if config.performance.max_concurrent_tasks == 0 {
errors.push("最大并发任务数必须大于 0".to_string());
}
if config.performance.profiling_sample_interval_ms < 10 {
errors.push("性能分析采样间隔不能小于 10ms".to_string());
}
if config.performance.work_stealing_queue_size < config.performance.max_concurrent_tasks {
errors.push("工作窃取队列大小不能小于最大并发任务数".to_string());
}
if config.monitoring.monitoring_interval_s == 0 {
errors.push("监控间隔必须大于 0".to_string());
}
if !matches!(config.logging.log_level.as_str(),
"trace" | "debug" | "info" | "warn" | "error") {
errors.push("日志级别必须是 trace、debug、info、warn 或 error".to_string());
}
if config.logging.max_log_file_size_mb == 0 {
errors.push("最大日志文件大小必须大于 0".to_string());
}
if config.security.resource_limit_mb == 0 {
errors.push("资源限制必须大于 0".to_string());
}
if config.security.max_execution_time_s == 0 {
errors.push("最大执行时间必须大于 0".to_string());
}
if config.network.http_port == 0 {
errors.push("HTTP 端口必须大于 0".to_string());
}
if config.network.http_port == config.network.websocket_port {
errors.push("HTTP 端口和 WebSocket 端口不能相同".to_string());
}
if config.network.max_connections == 0 {
errors.push("最大连接数必须大于 0".to_string());
}
if config.network.connection_timeout_s == 0 {
errors.push("连接超时必须大于 0".to_string());
}
if config.runtime.environment == "production" {
if !config.security.enable_sandbox {
errors.push("生产环境必须启用安全沙箱".to_string());
}
if !config.monitoring.enable_prometheus {
errors.push("生产环境必须启用 Prometheus 监控".to_string());
}
}
if !errors.is_empty() {
let error_msg: _ = format!("配置验证失败:\n{}", errors.join("\n"));
error!("{}", error_msg);
return Err(error_msg.into());
}
info!("配置验证通过");
Ok(())
}
pub async fn get_validation_report(&self) -> ValidationReport {
let config: _ = self.config.read().await;
let mut warnings = Vec::new();
if config.v8.max_heap_size_mb < 128 {
warnings.push("V8 堆大小过小,可能影响性能".to_string());
}
if config.memory.pool_size_mb < 64 {
warnings.push("内存池大小过小,可能影响性能".to_string());
}
if config.performance.max_concurrent_tasks > 10000 {
warnings.push("最大并发任务数过大,可能导致系统过载".to_string());
}
if config.logging.log_level == "trace" && config.runtime.environment == "production" {
warnings.push("生产环境不建议使用 trace 日志级别".to_string());
}
ValidationReport {
is_valid: true, errors: Vec::new(),
warnings,
config_snapshot: config.clone(),
}
}
pub async fn get_config_suggestions(&self) -> Result<Vec<ConfigSuggestion>, Box<dyn std::error::Error>> {
let config: _ = self.config.read().await;
let mut suggestions = Vec::new();
if config.v8.max_heap_size_mb < 256 {
suggestions.push(ConfigSuggestion {
path: "v8.max_heap_size_mb".to_string(),
current_value: serde_json::Value::Number(serde_json::Number::from(config.v8.max_heap_size_mb)),
suggested_value: serde_json::Value::Number(serde_json::Number::from(512)),
reason: "增加堆大小可以提高复杂脚本的性能".to_string(),
impact: "medium".to_string(),
});
}
if !config.memory.enable_zero_copy {
suggestions.push(ConfigSuggestion {
path: "memory.enable_zero_copy".to_string(),
current_value: serde_json::Value::Bool(false),
suggested_value: serde_json::Value::Bool(true),
reason: "启用零拷贝可以显著提高内存性能".to_string(),
impact: "high".to_string(),
});
}
if !config.performance.enable_fast_path {
suggestions.push(ConfigSuggestion {
path: "performance.enable_fast_path".to_string(),
current_value: serde_json::Value::Bool(false),
suggested_value: serde_json::Value::Bool(true),
reason: "启用快速路径优化可以提高执行性能".to_string(),
impact: "high".to_string(),
});
}
Ok(suggestions)
}
}
pub struct ValidationReport {
pub is_valid: bool,
pub errors: Vec<String>,
pub warnings: Vec<String>,
pub config_snapshot: RuntimeConfig,
}
pub struct ConfigSuggestion {
pub path: String,
pub current_value: serde_json::Value,
pub suggested_value: serde_json::Value,
pub reason: String,
pub impact: String, }
#[derive(Debug, Clone)]
pub struct ConfigSnapshot {
pub timestamp: std::time::SystemTime,
pub config: RuntimeConfig,
}
impl Clone for RuntimeConfigManager {
fn clone(&self) -> Self {
Self {
config: Arc::clone(&self.config),
config_path: self.config_path.clone(),
auto_tuner: self.auto_tuner.clone(),
change_callbacks: Arc::clone(&self.change_callbacks),
}
}
}
impl Default for RuntimeConfig {
fn default() -> Self {
Self {
runtime: RuntimeConfigSection {
environment: "development".to_string(),
instance_id: format!("amberjs-{}", uuid::Uuid::new_v4()),
startup_time_ms: 0,
version: env!("CARGO_PKG_VERSION").to_string(),
},
v8: V8ConfigSection {
max_heap_size_mb: 256,
initial_heap_size_mb: 64,
enable_jit: true,
jit_optimization_level: 3,
concurrent_marking: true,
incremental_marking: true,
concurrent_sweeping: true,
code_cache_size_mb: 32,
},
memory: MemoryConfigSection {
pool_size_mb: 128,
enable_zero_copy: true,
enable_compression: false,
leak_detection_interval_s: 60,
leak_threshold_mb: 10,
gc_tuning: GCTuningConfig {
trigger_threshold_percent: 80.0,
target_pause_time_ms: 10,
enable_incremental_gc: true,
enable_parallel_gc: true,
},
},
performance: PerformanceConfigSection {
enable_profiling: true,
profiling_sample_interval_ms: 100,
max_concurrent_tasks: 1000,
work_stealing_queue_size: 10000,
enable_fast_path: true,
cpu_affinity: None,
},
monitoring: MonitoringConfigSection {
enable_prometheus: true,
prometheus_addr: "127.0.0.1:9090".to_string(),
monitoring_interval_s: 5,
enable_intelligent_analysis: true,
enable_auto_tuning: true,
},
logging: LoggingConfigSection {
log_level: "info".to_string(),
enable_structured_logging: true,
log_file: None,
max_log_file_size_mb: 100,
log_rotation_count: 5,
},
security: SecurityConfigSection {
enable_sandbox: true,
resource_limit_mb: 512,
max_execution_time_s: 30,
disable_dangerous_functions: true,
},
network: NetworkConfigSection {
http_port: 8080,
websocket_port: 8081,
max_connections: 10000,
connection_timeout_s: 60,
},
}
}
}
#[cfg(test)]
mod tests {
#[tokio::test]
async fn test_runtime_config_manager_creation() {
let manager: _ = RuntimeConfigManager::new();
let config: _ = manager.get_config().await;
assert_eq!(config.v8.max_heap_size_mb, 256);
assert_eq!(config.memory.pool_size_mb, 128);
}
#[tokio::test]
async fn test_config_validation() {
let manager: _ = RuntimeConfigManager::new();
assert!(manager.validate_config().await.is_ok());
manager.update_config_value("v8.max_heap_size_mb", 0).await.unwrap();
assert!(manager.validate_config().await.is_err());
}
#[tokio::test]
async fn test_update_config_value() {
let manager: _ = RuntimeConfigManager::new();
manager.update_config_value("v8.max_heap_size_mb", 512).await.unwrap();
let config: _ = manager.get_config().await;
assert_eq!(config.v8.max_heap_size_mb, 512);
}
#[tokio::test]
async fn test_config_save_and_load() {
let mut manager = RuntimeConfigManager::new();
let temp_dir: _ = std::env::temp_dir();
let config_path: _ = temp_dir.join("amberjs_config_test.json");
manager.update_config_value("v8.max_heap_size_mb", 1024).await.unwrap();
manager.load_from_file(config_path.to_str().unwrap()).await.unwrap_or(());
let mut new_manager = RuntimeConfigManager::new();
new_manager.update_config_value("v8.max_heap_size_mb", 2048).await.unwrap();
let config: _ = new_manager.get_config().await;
assert_eq!(config.v8.max_heap_size_mb, 2048);
}
#[tokio::test]
async fn test_auto_tuner() {
let manager: _ = Arc::new(Mutex::new(RuntimeConfigManager::new()));
let tuner: _ = AutoTuner::new(manager.clone(), 60);
let result: _ = tuner.tune().await.unwrap();
assert!(result.applied_changes >= 0);
}
#[tokio::test]
async fn test_performance_metrics_collector() {
let collector: _ = PerformanceMetricsCollector::new();
collector.record_execution_time(100).await;
collector.record_memory_usage(256).await;
collector.record_cpu_usage(0.5).await;
let avg_time: _ = collector.get_average_execution_time().await.unwrap();
let avg_memory: _ = collector.get_average_memory_usage().await.unwrap();
let avg_cpu: _ = collector.get_average_cpu_usage().await.unwrap();
assert_eq!(avg_time, 100);
assert_eq!(avg_memory, 256);
assert_eq!(avg_cpu, 0.5);
}
#[tokio::test]
async fn test_environment_adaptation() {
let mut manager = RuntimeConfigManager::new();
manager.update_config_value("runtime.environment", "development").await.unwrap();
manager.adapt_for_environment().await.unwrap();
let config: _ = manager.get_config().await;
assert_eq!(config.logging.log_level, "debug");
manager.update_config_value("runtime.environment", "production").await.unwrap();
manager.adapt_for_environment().await.unwrap();
let config: _ = manager.get_config().await;
assert!(config.security.enable_sandbox);
assert!(config.monitoring.enable_prometheus);
}
#[tokio::test]
async fn test_config_suggestions() {
let manager: _ = RuntimeConfigManager::new();
manager.update_config_value("v8.max_heap_size_mb", 64).await.unwrap();
manager.update_config_value("memory.enable_zero_copy", false).await.unwrap();
let suggestions: _ = manager.get_config_suggestions().await.unwrap();
assert!(!suggestions.is_empty());
let has_heap_suggestion: _ = suggestions.iter()
.any(|s| s.path == "v8.max_heap_size_mb");
let has_zero_copy_suggestion: _ = suggestions.iter()
.any(|s| s.path == "memory.enable_zero_copy");
assert!(has_heap_suggestion);
assert!(has_zero_copy_suggestion);
}
#[tokio::test]
async fn test_validation_report() {
let manager: _ = RuntimeConfigManager::new();
let report: _ = manager.get_validation_report().await;
assert!(report.is_valid);
assert!(report.errors.is_empty());
}
#[tokio::test]
async fn test_config_snapshot() {
let manager: _ = RuntimeConfigManager::new();
let snapshot: _ = manager.get_config_snapshot().await;
assert_eq!(snapshot.config.v8.max_heap_size_mb, 256);
assert!(snapshot.timestamp <= std::time::SystemTime::now());
}
#[tokio::test]
async fn test_callback_registration() {
let manager: _ = RuntimeConfigManager::new();
let callback_called: _ = Arc::new(Mutex::new(AtomicBool::new(false)));
let callback_called_clone: _ = Arc::clone(callback_called);
let callback: ConfigChangeCallback = Box::new(move |_path, _value| {
callback_called_clone.store(true, std::sync::atomic::Ordering::Relaxed);
});
manager.add_change_callback(callback).await;
manager.update_config_value("v8.max_heap_size_mb", 512).await.unwrap();
assert!(true); }
#[tokio::test]
async fn test_get_defaults_for_environment() {
let dev_config: _ = RuntimeConfigManager::get_defaults_for_environment("development");
assert_eq!(dev_config.logging.log_level, "debug");
let prod_config: _ = RuntimeConfigManager::get_defaults_for_environment("production");
assert!(prod_config.security.enable_sandbox);
assert!(prod_config.monitoring.enable_prometheus);
let test_config: _ = RuntimeConfigManager::get_defaults_for_environment("testing");
assert!(!test_config.monitoring.enable_prometheus);
}
#[tokio::test]
async fn test_invalid_config_values() {
let manager: _ = RuntimeConfigManager::new();
let result: _ = manager.update_config_value("logging.log_level", "invalid_level").await;
assert!(result.is_ok()); assert!(manager.validate_config().await.is_err());
}
#[tokio::test]
async fn test_port_conflict() {
let manager: _ = RuntimeConfigManager::new();
manager.update_config_value("network.http_port", 8080).await.unwrap();
manager.update_config_value("network.websocket_port", 8080).await.unwrap();
assert!(manager.validate_config().await.is_err());
}
}