mirror of
https://github.com/postgresml/pgcat.git
synced 2026-03-26 02:16:30 +00:00
Reloadable config (#26)
* Reloadable config * readme * live config reload * test matrix
This commit is contained in:
106
src/config.rs
106
src/config.rs
@@ -1,12 +1,17 @@
|
||||
use arc_swap::{ArcSwap, Guard};
|
||||
use once_cell::sync::Lazy;
|
||||
use serde_derive::Deserialize;
|
||||
use tokio::fs::File;
|
||||
use tokio::io::AsyncReadExt;
|
||||
use toml;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::errors::Error;
|
||||
|
||||
static CONFIG: Lazy<ArcSwap<Config>> = Lazy::new(|| ArcSwap::from_pointee(Config::default()));
|
||||
|
||||
#[derive(Clone, PartialEq, Deserialize, Hash, std::cmp::Eq, Debug, Copy)]
|
||||
pub enum Role {
|
||||
Primary,
|
||||
@@ -39,12 +44,32 @@ pub struct Address {
|
||||
pub role: Role,
|
||||
}
|
||||
|
||||
impl Default for Address {
|
||||
fn default() -> Address {
|
||||
Address {
|
||||
host: String::from("127.0.0.1"),
|
||||
port: String::from("5432"),
|
||||
shard: 0,
|
||||
role: Role::Replica,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Hash, std::cmp::Eq, Deserialize, Debug)]
|
||||
pub struct User {
|
||||
pub name: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
impl Default for User {
|
||||
fn default() -> User {
|
||||
User {
|
||||
name: String::from("postgres"),
|
||||
password: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct General {
|
||||
pub host: String,
|
||||
@@ -54,6 +79,22 @@ pub struct General {
|
||||
pub connect_timeout: u64,
|
||||
pub healthcheck_timeout: u64,
|
||||
pub ban_time: i64,
|
||||
pub statsd_address: String,
|
||||
}
|
||||
|
||||
impl Default for General {
|
||||
fn default() -> General {
|
||||
General {
|
||||
host: String::from("localhost"),
|
||||
port: 5432,
|
||||
pool_size: 15,
|
||||
pool_mode: String::from("transaction"),
|
||||
connect_timeout: 5000,
|
||||
healthcheck_timeout: 1000,
|
||||
ban_time: 60,
|
||||
statsd_address: String::from("127.0.0.1:8125"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
@@ -62,6 +103,15 @@ pub struct Shard {
|
||||
pub database: String,
|
||||
}
|
||||
|
||||
impl Default for Shard {
|
||||
fn default() -> Shard {
|
||||
Shard {
|
||||
servers: vec![(String::from("localhost"), 5432, String::from("primary"))],
|
||||
database: String::from("postgres"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct QueryRouter {
|
||||
pub default_role: String,
|
||||
@@ -69,6 +119,16 @@ pub struct QueryRouter {
|
||||
pub primary_reads_enabled: bool,
|
||||
}
|
||||
|
||||
impl Default for QueryRouter {
|
||||
fn default() -> QueryRouter {
|
||||
QueryRouter {
|
||||
default_role: String::from("any"),
|
||||
query_parser_enabled: false,
|
||||
primary_reads_enabled: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct Config {
|
||||
pub general: General,
|
||||
@@ -77,8 +137,36 @@ pub struct Config {
|
||||
pub query_router: QueryRouter,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Config {
|
||||
Config {
|
||||
general: General::default(),
|
||||
user: User::default(),
|
||||
shards: HashMap::from([(String::from("1"), Shard::default())]),
|
||||
query_router: QueryRouter::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn show(&self) {
|
||||
println!("> Pool size: {}", self.general.pool_size);
|
||||
println!("> Pool mode: {}", self.general.pool_mode);
|
||||
println!("> Ban time: {}s", self.general.ban_time);
|
||||
println!(
|
||||
"> Healthcheck timeout: {}ms",
|
||||
self.general.healthcheck_timeout
|
||||
);
|
||||
println!("> Connection timeout: {}ms", self.general.connect_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_config() -> Guard<Arc<Config>> {
|
||||
CONFIG.load()
|
||||
}
|
||||
|
||||
/// Parse the config.
|
||||
pub async fn parse(path: &str) -> Result<Config, Error> {
|
||||
pub async fn parse(path: &str) -> Result<(), Error> {
|
||||
let mut contents = String::new();
|
||||
let mut file = match File::open(path).await {
|
||||
Ok(file) => file,
|
||||
@@ -163,7 +251,9 @@ pub async fn parse(path: &str) -> Result<Config, Error> {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(config)
|
||||
CONFIG.store(Arc::new(config.clone()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -172,11 +262,11 @@ mod test {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_config() {
|
||||
let config = parse("pgcat.toml").await.unwrap();
|
||||
assert_eq!(config.general.pool_size, 15);
|
||||
assert_eq!(config.shards.len(), 3);
|
||||
assert_eq!(config.shards["1"].servers[0].0, "127.0.0.1");
|
||||
assert_eq!(config.shards["0"].servers[0].2, "primary");
|
||||
assert_eq!(config.query_router.default_role, "any");
|
||||
parse("pgcat.toml").await.unwrap();
|
||||
assert_eq!(get_config().general.pool_size, 15);
|
||||
assert_eq!(get_config().shards.len(), 3);
|
||||
assert_eq!(get_config().shards["1"].servers[0].0, "127.0.0.1");
|
||||
assert_eq!(get_config().shards["0"].servers[0].2, "primary");
|
||||
assert_eq!(get_config().query_router.default_role, "any");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user