#[derive(Clone, Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Config {
pub tidb: TiDBConfig,
}
#[derive(Clone, Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TiDBConfig {
pub host: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub port: Option<u16>,
pub username: String,
pub password: String,
pub database_name: String,
#[serde(default)]
pub pool_options: PoolOptions,
#[serde(skip_serializing_if = "Option::is_none")]
pub ssl_ca: Option<String>,
}
impl TiDBConfig {
pub fn get_host(&self) -> String {
let port = self.port.unwrap_or(4000);
format!("{}:{}", self.host, port)
}
}
fn default_max_connections() -> u32 {
10
}
fn default_min_connections() -> u32 {
1
}
fn default_acquire_timeout() -> u64 {
30
}
fn default_idle_timeout() -> u64 {
300
}
fn default_max_lifetime() -> u64 {
1800
}
fn default_is_lazy() -> bool {
true
}
fn default_statement_cache_capacity() -> usize {
100
}
#[derive(Clone, Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PoolOptions {
#[serde(default = "default_max_connections")]
pub max_connections: u32,
#[serde(default = "default_min_connections")]
pub min_connections: u32,
#[serde(default = "default_acquire_timeout")]
pub acquire_timeout: u64,
#[serde(default = "default_idle_timeout")]
pub idle_timeout: u64,
#[serde(default = "default_max_lifetime")]
pub max_lifetime: u64,
#[serde(default = "default_is_lazy")]
pub is_lazy: bool,
#[serde(default = "default_statement_cache_capacity")]
pub statement_cache_capacity: usize,
}
impl Default for PoolOptions {
fn default() -> Self {
PoolOptions {
max_connections: default_max_connections(),
min_connections: default_min_connections(),
acquire_timeout: default_acquire_timeout(),
idle_timeout: default_idle_timeout(),
max_lifetime: default_max_lifetime(),
is_lazy: default_is_lazy(),
statement_cache_capacity: 100,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use toml;
#[test]
fn test_default_pool_options() {
let default_options = PoolOptions::default();
assert_eq!(default_options.max_connections, 10);
assert_eq!(default_options.min_connections, 1);
assert_eq!(default_options.acquire_timeout, 30);
assert_eq!(default_options.idle_timeout, 300);
assert_eq!(default_options.max_lifetime, 1800);
assert!(default_options.is_lazy);
}
#[test]
fn test_deserialize_pool_options_from_toml() {
let toml_data = r#"
maxConnections = 10
minConnections = 3
acquireTimeout = 15
idleTimeout = 600
maxLifetime = 3600
isLazy = false
"#;
let pool_options: PoolOptions =
toml::from_str(toml_data).expect("Failed to deserialize TOML");
assert_eq!(pool_options.max_connections, 10);
assert_eq!(pool_options.min_connections, 3);
assert_eq!(pool_options.acquire_timeout, 15);
assert_eq!(pool_options.idle_timeout, 600);
assert_eq!(pool_options.max_lifetime, 3600);
assert!(!pool_options.is_lazy);
}
#[test]
fn test_deserialize_pool_options_with_missing_fields() {
let toml_data = r#"
maxConnections = 10
isLazy = true
"#;
let pool_options: PoolOptions =
toml::from_str(toml_data).expect("Failed to deserialize TOML");
assert_eq!(pool_options.max_connections, 10);
assert_eq!(pool_options.min_connections, 1); assert_eq!(pool_options.acquire_timeout, 30); assert_eq!(pool_options.idle_timeout, 300); assert_eq!(pool_options.max_lifetime, 1800); assert!(pool_options.is_lazy);
}
#[test]
fn test_serialize_pool_options_to_toml() {
let pool_options = PoolOptions {
max_connections: 20,
min_connections: 5,
acquire_timeout: 60,
idle_timeout: 1200,
max_lifetime: 7200,
is_lazy: false,
statement_cache_capacity: 100,
};
let toml_data = toml::to_string(&pool_options).expect("Failed to serialize to TOML");
let expected_toml = r#"
maxConnections = 20
minConnections = 5
acquireTimeout = 60
idleTimeout = 1200
maxLifetime = 7200
isLazy = false
statementCacheCapacity = 100
"#
.trim();
assert_eq!(toml_data.trim(), expected_toml);
}
#[test]
fn test_get_host_with_port() {
let config = TiDBConfig {
host: "127.0.0.1".into(),
port: Some(5000),
username: "admin".into(),
password: "secret".into(),
database_name: "mydb".into(),
pool_options: PoolOptions::default(),
ssl_ca: None,
};
assert_eq!(config.get_host(), "127.0.0.1:5000");
}
#[test]
fn test_get_host_without_port() {
let config = TiDBConfig {
host: "127.0.0.1".into(),
port: None,
username: "admin".into(),
password: "secret".into(),
database_name: "mydb".into(),
pool_options: PoolOptions::default(),
ssl_ca: None,
};
assert_eq!(config.get_host(), "127.0.0.1:4000");
}
#[test]
fn test_deserialize_tidb_config_from_toml() {
let toml_data = r#"
host = "127.0.0.1"
port = 4000
username = "admin"
password = "secret"
databaseName = "mydb"
[poolOptions]
maxConnections = 10
minConnections = 5
acquireTimeout = 30
idleTimeout = 300
maxLifetime = 3600
isLazy = true
"#;
let config: TiDBConfig = toml::from_str(toml_data).expect("Failed to deserialize TOML");
assert_eq!(config.host, "127.0.0.1");
assert_eq!(config.port, Some(4000));
assert_eq!(config.username, "admin");
assert_eq!(config.password, "secret");
assert_eq!(config.database_name, "mydb");
assert_eq!(config.pool_options.max_connections, 10);
assert_eq!(config.pool_options.min_connections, 5);
assert_eq!(config.pool_options.acquire_timeout, 30);
assert_eq!(config.pool_options.idle_timeout, 300);
assert_eq!(config.pool_options.max_lifetime, 3600);
assert!(config.pool_options.is_lazy);
}
#[test]
fn test_serialize_tidb_config_to_toml() {
let config = TiDBConfig {
host: "127.0.0.1".into(),
port: Some(4000),
username: "admin".into(),
password: "secret".into(),
database_name: "mydb".into(),
pool_options: PoolOptions {
max_connections: 10,
min_connections: 5,
acquire_timeout: 30,
idle_timeout: 300,
max_lifetime: 3600,
is_lazy: true,
statement_cache_capacity: 100,
},
ssl_ca: None,
};
let toml_data = toml::to_string(&config).expect("Failed to serialize to TOML");
let expected_toml = r#"
host = "127.0.0.1"
port = 4000
username = "admin"
password = "secret"
databaseName = "mydb"
[poolOptions]
maxConnections = 10
minConnections = 5
acquireTimeout = 30
idleTimeout = 300
maxLifetime = 3600
isLazy = true
statementCacheCapacity = 100
"#
.trim();
assert_eq!(toml_data.trim(), expected_toml);
}
#[test]
fn test_deserialize_tidb_config_with_missing_optional_fields() {
let toml_data = r#"
host = "127.0.0.1"
username = "admin"
password = "secret"
databaseName = "mydb"
[poolOptions]
isLazy = true
"#;
let config: TiDBConfig = toml::from_str(toml_data).expect("Failed to deserialize TOML");
assert_eq!(config.host, "127.0.0.1");
assert_eq!(config.port, None); assert_eq!(config.username, "admin");
assert_eq!(config.password, "secret");
assert_eq!(config.database_name, "mydb");
assert_eq!(config.pool_options.max_connections, 10); assert_eq!(config.pool_options.min_connections, 1); assert_eq!(config.pool_options.acquire_timeout, 30); assert_eq!(config.pool_options.idle_timeout, 300); assert_eq!(config.pool_options.max_lifetime, 1800); assert!(config.pool_options.is_lazy);
}
}