1use serde::{Deserialize, Serialize};
2use std::fs;
3use std::path::Path;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Config {
8 pub bind_addr: String,
10
11 pub port: u16,
13
14 pub threads: usize,
16
17 pub data_path: Option<String>,
19
20 pub max_connections_per_thread: usize,
22
23 pub connection_buffer_size: usize,
25
26 pub tcp_nodelay: bool,
28
29 pub max_pipeline_depth: usize,
31
32 pub numa_aware: bool,
34
35 pub max_memory_per_shard: Option<usize>,
37
38 pub enable_ttl: bool,
40
41 pub file_size: Option<u64>,
44
45 pub log_level: String,
47}
48
49impl Default for Config {
50 fn default() -> Self {
51 Self {
52 bind_addr: "127.0.0.1".to_string(),
53 port: 6379,
54 threads: num_cpus::get(),
55 data_path: None,
56 max_connections_per_thread: 10000,
57 connection_buffer_size: 16 * 1024, tcp_nodelay: true,
59 max_pipeline_depth: 1000,
60 numa_aware: false,
61 max_memory_per_shard: Some(1024 * 1024 * 1024), enable_ttl: true,
63 file_size: Some(10 * 1024 * 1024 * 1024), log_level: "info".to_string(),
65 }
66 }
67}
68
69impl Config {
70 pub fn from_file<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
83 let contents = fs::read_to_string(path)?;
84 let config = toml::from_str(&contents)?;
85 Ok(config)
86 }
87
88 pub fn to_file<P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()> {
90 let contents = toml::to_string_pretty(self)?;
91 fs::write(path, contents)?;
92 Ok(())
93 }
94
95 pub fn validate(&self) -> anyhow::Result<()> {
97 if self.threads == 0 {
98 anyhow::bail!("threads must be > 0");
99 }
100
101 if self.port == 0 {
102 anyhow::bail!("port must be > 0");
103 }
104
105 if self.connection_buffer_size < 1024 {
106 anyhow::bail!("connection_buffer_size must be >= 1024");
107 }
108
109 Ok(())
110 }
111}