use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use validator::Validate;
use zentinel_common::types::CircuitBreakerConfig;
use crate::routes::FailureMode;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[derive(Default)]
pub enum BodyStreamingMode {
#[default]
Buffer,
Stream,
Hybrid {
#[serde(default = "default_hybrid_threshold")]
buffer_threshold: usize,
},
}
fn default_hybrid_threshold() -> usize {
64 * 1024 }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentPoolConfig {
#[serde(default = "default_connections_per_agent")]
pub connections_per_agent: usize,
#[serde(default)]
pub load_balance_strategy: LoadBalanceStrategy,
#[serde(default = "default_connect_timeout_ms")]
pub connect_timeout_ms: u64,
#[serde(default = "default_reconnect_interval_ms")]
pub reconnect_interval_ms: u64,
#[serde(default = "default_max_reconnect_attempts")]
pub max_reconnect_attempts: usize,
#[serde(default = "default_drain_timeout_ms")]
pub drain_timeout_ms: u64,
#[serde(default = "default_max_concurrent_per_connection")]
pub max_concurrent_per_connection: usize,
#[serde(default = "default_health_check_interval_ms")]
pub health_check_interval_ms: u64,
}
impl Default for AgentPoolConfig {
fn default() -> Self {
Self {
connections_per_agent: default_connections_per_agent(),
load_balance_strategy: LoadBalanceStrategy::default(),
connect_timeout_ms: default_connect_timeout_ms(),
reconnect_interval_ms: default_reconnect_interval_ms(),
max_reconnect_attempts: default_max_reconnect_attempts(),
drain_timeout_ms: default_drain_timeout_ms(),
max_concurrent_per_connection: default_max_concurrent_per_connection(),
health_check_interval_ms: default_health_check_interval_ms(),
}
}
}
fn default_connections_per_agent() -> usize {
4
}
fn default_connect_timeout_ms() -> u64 {
5000
}
fn default_reconnect_interval_ms() -> u64 {
5000
}
fn default_max_reconnect_attempts() -> usize {
3
}
fn default_drain_timeout_ms() -> u64 {
30000
}
fn default_max_concurrent_per_connection() -> usize {
100
}
fn default_health_check_interval_ms() -> u64 {
10000
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum LoadBalanceStrategy {
#[default]
RoundRobin,
LeastConnections,
HealthBased,
Random,
}
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
pub struct AgentConfig {
pub id: String,
#[serde(rename = "type")]
pub agent_type: AgentType,
pub transport: AgentTransport,
pub events: Vec<AgentEvent>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pool: Option<AgentPoolConfig>,
#[serde(default = "default_agent_timeout")]
pub timeout_ms: u64,
#[serde(default)]
pub failure_mode: FailureMode,
#[serde(default)]
pub circuit_breaker: Option<CircuitBreakerConfig>,
pub max_request_body_bytes: Option<usize>,
pub max_response_body_bytes: Option<usize>,
#[serde(default)]
pub request_body_mode: BodyStreamingMode,
#[serde(default)]
pub response_body_mode: BodyStreamingMode,
#[serde(default = "default_chunk_timeout")]
pub chunk_timeout_ms: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub config: Option<serde_json::Value>,
#[serde(default = "default_max_concurrent_calls")]
pub max_concurrent_calls: usize,
}
fn default_chunk_timeout() -> u64 {
5000 }
fn default_max_concurrent_calls() -> usize {
100 }
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AgentType {
Waf,
Auth,
RateLimit,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AgentTransport {
UnixSocket { path: PathBuf },
Grpc {
address: String,
tls: Option<AgentTlsConfig>,
},
Http {
url: String,
tls: Option<AgentTlsConfig>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentTlsConfig {
#[serde(default)]
pub insecure_skip_verify: bool,
pub ca_cert: Option<PathBuf>,
pub client_cert: Option<PathBuf>,
pub client_key: Option<PathBuf>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AgentEvent {
RequestHeaders,
RequestBody,
ResponseHeaders,
ResponseBody,
Log,
WebSocketFrame,
Guardrail,
}
fn default_agent_timeout() -> u64 {
1000
}