use serde::Deserialize;
use serde::Serialize;
use super::default::default_raft_config;
use super::default::default_rocksdb_config;
use super::endpoint::Endpoint;
use crate::error::{Error, Result};
#[derive(Debug, Clone)]
pub struct Config {
pub node_id: u64,
pub raft: RaftConfig,
pub rocksdb: RocksdbConfig,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct RocksdbConfig {
pub data_path: String,
pub max_open_files: i32,
}
#[derive(Debug, Clone)]
pub struct RaftConfig {
pub endpoint: Endpoint,
pub advertise_endpoint: Endpoint,
pub single: bool,
pub join: Vec<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
pub(crate) struct RawConfig {
pub node_id: u64,
#[serde(default = "default_raft_config")]
pub raft: RawRaftConfig,
#[serde(default = "default_rocksdb_config")]
pub rocksdb: RocksdbConfig,
}
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
pub(crate) struct RawRaftConfig {
pub address: String,
pub advertise_host: String,
pub single: bool,
pub join: Vec<String>,
}
impl Config {
pub(crate) fn validate_and_parse(raw: RawConfig) -> Result<Self> {
if raw.raft.single && !raw.raft.join.is_empty() {
return Err(Error::config(
"'single' mode cannot be used together with 'join' configuration",
));
}
let endpoint = Endpoint::parse(&raw.raft.address)?;
let advertise_endpoint = if raw.raft.advertise_host.is_empty() {
endpoint.clone()
} else {
Endpoint::new(&raw.raft.advertise_host, endpoint.port())
};
Ok(Config {
node_id: raw.node_id,
raft: RaftConfig {
endpoint,
advertise_endpoint,
single: raw.raft.single,
join: raw.raft.join,
},
rocksdb: RocksdbConfig {
data_path: raw.rocksdb.data_path,
max_open_files: raw.rocksdb.max_open_files,
},
})
}
}
impl<'de> Deserialize<'de> for Config {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let raw = RawConfig::deserialize(deserializer)?;
Self::validate_and_parse(raw).map_err(serde::de::Error::custom)
}
}
impl Serialize for Config {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let raw = RawConfig {
node_id: self.node_id,
raft: RawRaftConfig {
address: self.raft.endpoint.to_string(),
advertise_host: self.raft.advertise_endpoint.addr().to_string(),
single: self.raft.single,
join: self.raft.join.clone(),
},
rocksdb: self.rocksdb.clone(),
};
raw.serialize(serializer)
}
}