use std::time::Duration;
use serde::{Deserialize, Serialize};
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default,
)]
pub enum Environment {
#[default]
Development,
Testing,
Production,
Custom,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProcessorConfig {
pub max_queue_size: usize,
pub max_concurrent_tasks: usize,
pub task_timeout: Duration,
pub max_retries: u32,
pub retry_delay: Duration,
pub cleanup_timeout: Duration,
}
impl Default for ProcessorConfig {
fn default() -> Self {
Self {
max_queue_size: 1000,
max_concurrent_tasks: 10,
task_timeout: Duration::from_secs(30),
max_retries: 3,
retry_delay: Duration::from_secs(1),
cleanup_timeout: Duration::from_secs(30),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceConfig {
pub enable_monitoring: bool,
pub middleware_timeout_ms: u64,
pub log_threshold_ms: u64,
pub task_receive_timeout_ms: u64,
pub enable_detailed_logging: bool,
pub metrics_sampling_rate: f64,
}
impl Default for PerformanceConfig {
fn default() -> Self {
Self {
enable_monitoring: false,
middleware_timeout_ms: 500,
log_threshold_ms: 50,
task_receive_timeout_ms: 5000,
enable_detailed_logging: false,
metrics_sampling_rate: 1.0,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EventConfig {
pub max_queue_size: usize,
pub handler_timeout: Duration,
pub enable_persistence: bool,
pub batch_size: usize,
pub max_concurrent_handlers: usize,
}
impl Default for EventConfig {
fn default() -> Self {
Self {
max_queue_size: 10000,
handler_timeout: Duration::from_secs(5),
enable_persistence: false,
batch_size: 100,
max_concurrent_handlers: 5,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HistoryConfig {
pub max_entries: usize,
pub enable_compression: bool,
pub persistence_interval: Duration,
}
impl Default for HistoryConfig {
fn default() -> Self {
Self {
max_entries: 100,
enable_compression: false,
persistence_interval: Duration::from_secs(60),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExtensionConfig {
pub load_timeout: Duration,
pub enable_hot_reload: bool,
pub max_memory_mb: usize,
pub enable_sandbox: bool,
pub xml_schema_paths: Vec<String>,
pub enable_xml_auto_reload: bool,
pub xml_parse_timeout: Duration,
}
impl Default for ExtensionConfig {
fn default() -> Self {
Self {
load_timeout: Duration::from_secs(10),
enable_hot_reload: false,
max_memory_mb: 100,
enable_sandbox: true,
xml_schema_paths: Vec::new(),
enable_xml_auto_reload: false,
xml_parse_timeout: Duration::from_secs(5),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CacheConfig {
pub max_entries: usize,
pub entry_ttl: Duration,
pub enable_lru: bool,
pub cleanup_interval: Duration,
}
impl Default for CacheConfig {
fn default() -> Self {
Self {
max_entries: 1000,
entry_ttl: Duration::from_secs(300), enable_lru: true,
cleanup_interval: Duration::from_secs(60),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum RuntimeType {
Auto,
Sync,
Async,
Actor,
}
impl Default for RuntimeType {
fn default() -> Self {
RuntimeType::Auto
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct RuntimeConfig {
#[serde(default)]
pub runtime_type: RuntimeType,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ForgeConfig {
#[serde(default)]
pub environment: Environment,
#[serde(default)]
pub runtime: RuntimeConfig,
#[serde(default)]
pub processor: ProcessorConfig,
#[serde(default)]
pub performance: PerformanceConfig,
#[serde(default)]
pub event: EventConfig,
#[serde(default)]
pub history: HistoryConfig,
#[serde(default)]
pub extension: ExtensionConfig,
#[serde(default)]
pub cache: CacheConfig,
}
impl ForgeConfig {
pub fn for_environment(env: Environment) -> Self {
match env {
Environment::Development => Self::development(),
Environment::Testing => Self::testing(),
Environment::Production => Self::production(),
Environment::Custom => Self::default(),
}
}
pub fn development() -> Self {
Self {
environment: Environment::Development,
runtime: RuntimeConfig::default(),
processor: ProcessorConfig {
max_queue_size: 500,
max_concurrent_tasks: 5,
task_timeout: Duration::from_secs(60),
max_retries: 5,
retry_delay: Duration::from_secs(2),
cleanup_timeout: Duration::from_secs(60),
},
performance: PerformanceConfig {
enable_monitoring: true,
middleware_timeout_ms: 10000, log_threshold_ms: 100,
task_receive_timeout_ms: 30000, enable_detailed_logging: true,
metrics_sampling_rate: 1.0,
},
event: EventConfig {
max_queue_size: 5000,
handler_timeout: Duration::from_secs(10),
enable_persistence: false,
batch_size: 50,
max_concurrent_handlers: 3,
},
history: HistoryConfig {
max_entries: 200,
enable_compression: false,
persistence_interval: Duration::from_secs(30),
},
extension: ExtensionConfig {
load_timeout: Duration::from_secs(30),
enable_hot_reload: true,
max_memory_mb: 200,
enable_sandbox: false, xml_schema_paths: Vec::new(),
enable_xml_auto_reload: true,
xml_parse_timeout: Duration::from_secs(10),
},
cache: CacheConfig {
max_entries: 500,
entry_ttl: Duration::from_secs(600), enable_lru: true,
cleanup_interval: Duration::from_secs(30),
},
}
}
pub fn testing() -> Self {
Self {
environment: Environment::Testing,
runtime: RuntimeConfig::default(),
processor: ProcessorConfig {
max_queue_size: 100,
max_concurrent_tasks: 3,
task_timeout: Duration::from_secs(10),
max_retries: 2,
retry_delay: Duration::from_millis(500),
cleanup_timeout: Duration::from_secs(10),
},
performance: PerformanceConfig {
enable_monitoring: true,
middleware_timeout_ms: 2000, log_threshold_ms: 50,
task_receive_timeout_ms: 5000, enable_detailed_logging: false,
metrics_sampling_rate: 0.1, },
event: EventConfig {
max_queue_size: 1000,
handler_timeout: Duration::from_secs(2),
enable_persistence: false,
batch_size: 20,
max_concurrent_handlers: 2,
},
history: HistoryConfig {
max_entries: 50,
enable_compression: false,
persistence_interval: Duration::from_secs(10),
},
extension: ExtensionConfig {
load_timeout: Duration::from_secs(5),
enable_hot_reload: false,
max_memory_mb: 50,
enable_sandbox: true,
xml_schema_paths: Vec::new(),
enable_xml_auto_reload: false,
xml_parse_timeout: Duration::from_secs(3),
},
cache: CacheConfig {
max_entries: 100,
entry_ttl: Duration::from_secs(60), enable_lru: true,
cleanup_interval: Duration::from_secs(10),
},
}
}
pub fn production() -> Self {
Self {
environment: Environment::Production,
runtime: RuntimeConfig::default(),
processor: ProcessorConfig {
max_queue_size: 10000,
max_concurrent_tasks: 50,
task_timeout: Duration::from_secs(30),
max_retries: 3,
retry_delay: Duration::from_millis(100),
cleanup_timeout: Duration::from_secs(30),
},
performance: PerformanceConfig {
enable_monitoring: true,
middleware_timeout_ms: 1000, log_threshold_ms: 50,
task_receive_timeout_ms: 5000, enable_detailed_logging: false,
metrics_sampling_rate: 0.01, },
event: EventConfig {
max_queue_size: 50000,
handler_timeout: Duration::from_secs(5),
enable_persistence: true,
batch_size: 500,
max_concurrent_handlers: 10,
},
history: HistoryConfig {
max_entries: 1000,
enable_compression: true,
persistence_interval: Duration::from_secs(300), },
extension: ExtensionConfig {
load_timeout: Duration::from_secs(10),
enable_hot_reload: false,
max_memory_mb: 500,
enable_sandbox: true,
xml_schema_paths: Vec::new(),
enable_xml_auto_reload: false,
xml_parse_timeout: Duration::from_secs(5),
},
cache: CacheConfig {
max_entries: 10000,
entry_ttl: Duration::from_secs(1800), enable_lru: true,
cleanup_interval: Duration::from_secs(300), },
}
}
pub fn builder() -> ForgeConfigBuilder {
ForgeConfigBuilder::new()
}
pub fn validate(&self) -> Result<(), ConfigValidationError> {
if self.processor.max_queue_size == 0 {
return Err(ConfigValidationError::InvalidValue {
field: "processor.max_queue_size".to_string(),
value: "0".to_string(),
reason: "队列大小必须大于0".to_string(),
});
}
if self.processor.max_concurrent_tasks == 0 {
return Err(ConfigValidationError::InvalidValue {
field: "processor.max_concurrent_tasks".to_string(),
value: "0".to_string(),
reason: "并发任务数必须大于0".to_string(),
});
}
if self.processor.task_timeout.is_zero() {
return Err(ConfigValidationError::InvalidValue {
field: "processor.task_timeout".to_string(),
value: "0".to_string(),
reason: "任务超时时间必须大于0".to_string(),
});
}
if self.performance.middleware_timeout_ms == 0 {
return Err(ConfigValidationError::InvalidValue {
field: "performance.middleware_timeout_ms".to_string(),
value: "0".to_string(),
reason: "中间件超时时间必须大于0".to_string(),
});
}
if !(0.0..=1.0).contains(&self.performance.metrics_sampling_rate) {
return Err(ConfigValidationError::InvalidValue {
field: "performance.metrics_sampling_rate".to_string(),
value: self.performance.metrics_sampling_rate.to_string(),
reason: "采样率必须在0.0到1.0之间".to_string(),
});
}
if self.event.max_queue_size == 0 {
return Err(ConfigValidationError::InvalidValue {
field: "event.max_queue_size".to_string(),
value: "0".to_string(),
reason: "事件队列大小必须大于0".to_string(),
});
}
if self.history.max_entries == 0 {
return Err(ConfigValidationError::InvalidValue {
field: "history.max_entries".to_string(),
value: "0".to_string(),
reason: "历史记录条数必须大于0".to_string(),
});
}
if self.cache.max_entries == 0 {
return Err(ConfigValidationError::InvalidValue {
field: "cache.max_entries".to_string(),
value: "0".to_string(),
reason: "缓存条目数必须大于0".to_string(),
});
}
Ok(())
}
pub fn get_tuning_suggestions(&self) -> Vec<String> {
let mut suggestions = Vec::new();
match self.environment {
Environment::Development => {
if !self.performance.enable_detailed_logging {
suggestions
.push("开发环境建议启用详细日志记录".to_string());
}
if self.extension.enable_sandbox {
suggestions
.push("开发环境可以关闭扩展沙箱以便调试".to_string());
}
},
Environment::Production => {
if self.performance.enable_detailed_logging {
suggestions.push(
"生产环境建议关闭详细日志记录以提高性能".to_string(),
);
}
if self.performance.metrics_sampling_rate > 0.1 {
suggestions.push(
"生产环境建议降低指标采样率以减少开销".to_string(),
);
}
if !self.extension.enable_sandbox {
suggestions.push(
"生产环境建议启用扩展沙箱以提高安全性".to_string(),
);
}
},
Environment::Testing => {
if self.processor.task_timeout > Duration::from_secs(30) {
suggestions
.push("测试环境建议使用较短的任务超时时间".to_string());
}
},
Environment::Custom => {
suggestions
.push("自定义环境,请根据实际需求调整配置".to_string());
},
}
suggestions
}
}
#[derive(Debug, Clone)]
pub enum ConfigValidationError {
InvalidValue { field: String, value: String, reason: String },
Conflict { field1: String, field2: String, reason: String },
MissingRequired { field: String },
}
impl std::fmt::Display for ConfigValidationError {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
match self {
ConfigValidationError::InvalidValue { field, value, reason } => {
write!(f, "配置字段 '{field}' 的值 '{value}' 无效: {reason}")
},
ConfigValidationError::Conflict { field1, field2, reason } => {
write!(f, "配置字段 '{field1}' 和 '{field2}' 冲突: {reason}")
},
ConfigValidationError::MissingRequired { field } => {
write!(f, "缺少必需的配置字段: {field}")
},
}
}
}
impl std::error::Error for ConfigValidationError {}
#[derive(Debug, Clone)]
pub struct ForgeConfigBuilder {
config: ForgeConfig,
}
impl ForgeConfigBuilder {
pub fn new() -> Self {
Self { config: ForgeConfig::default() }
}
pub fn from_config(config: ForgeConfig) -> Self {
Self { config }
}
pub fn environment(
mut self,
env: Environment,
) -> Self {
self.config.environment = env;
self
}
pub fn processor_config(
mut self,
config: ProcessorConfig,
) -> Self {
self.config.processor = config;
self
}
pub fn performance_config(
mut self,
config: PerformanceConfig,
) -> Self {
self.config.performance = config;
self
}
pub fn event_config(
mut self,
config: EventConfig,
) -> Self {
self.config.event = config;
self
}
pub fn history_config(
mut self,
config: HistoryConfig,
) -> Self {
self.config.history = config;
self
}
pub fn extension_config(
mut self,
config: ExtensionConfig,
) -> Self {
self.config.extension = config;
self
}
pub fn cache_config(
mut self,
config: CacheConfig,
) -> Self {
self.config.cache = config;
self
}
pub fn max_queue_size(
mut self,
size: usize,
) -> Self {
self.config.processor.max_queue_size = size;
self
}
pub fn max_concurrent_tasks(
mut self,
count: usize,
) -> Self {
self.config.processor.max_concurrent_tasks = count;
self
}
pub fn task_timeout(
mut self,
timeout: Duration,
) -> Self {
self.config.processor.task_timeout = timeout;
self
}
pub fn middleware_timeout(
mut self,
timeout_ms: u64,
) -> Self {
self.config.performance.middleware_timeout_ms = timeout_ms;
self
}
pub fn enable_monitoring(
mut self,
enable: bool,
) -> Self {
self.config.performance.enable_monitoring = enable;
self
}
pub fn history_limit(
mut self,
limit: usize,
) -> Self {
self.config.history.max_entries = limit;
self
}
pub fn build(self) -> Result<ForgeConfig, ConfigValidationError> {
self.config.validate()?;
Ok(self.config)
}
pub fn build_unchecked(self) -> ForgeConfig {
self.config
}
}
impl Default for ForgeConfigBuilder {
fn default() -> Self {
Self::new()
}
}
impl ForgeConfig {
pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
serde_json::from_str(json)
}
pub fn to_json(&self) -> Result<String, serde_json::Error> {
serde_json::to_string_pretty(self)
}
pub fn from_env_override(mut self) -> Self {
use std::env;
if let Ok(env_str) = env::var("FORGE_ENVIRONMENT") {
match env_str.to_lowercase().as_str() {
"development" | "dev" => {
self.environment = Environment::Development
},
"testing" | "test" => self.environment = Environment::Testing,
"production" | "prod" => {
self.environment = Environment::Production
},
"custom" => self.environment = Environment::Custom,
_ => {},
}
}
if let Ok(size) = env::var("FORGE_PROCESSOR_MAX_QUEUE_SIZE") {
if let Ok(size) = size.parse::<usize>() {
self.processor.max_queue_size = size;
}
}
if let Ok(tasks) = env::var("FORGE_PROCESSOR_MAX_CONCURRENT_TASKS") {
if let Ok(tasks) = tasks.parse::<usize>() {
self.processor.max_concurrent_tasks = tasks;
}
}
if let Ok(enable) = env::var("FORGE_PERFORMANCE_ENABLE_MONITORING") {
self.performance.enable_monitoring =
enable.to_lowercase() == "true";
}
if let Ok(timeout) = env::var("FORGE_PERFORMANCE_MIDDLEWARE_TIMEOUT_MS")
{
if let Ok(timeout) = timeout.parse::<u64>() {
self.performance.middleware_timeout_ms = timeout;
}
}
self
}
pub fn merge_with(
mut self,
other: &ForgeConfig,
) -> Self {
if other.environment != Environment::Development {
self.environment = other.environment;
}
self.processor = other.processor.clone();
self.performance = other.performance.clone();
self.event = other.event.clone();
self.history = other.history.clone();
self.extension = other.extension.clone();
self.cache = other.cache.clone();
self
}
}