diff options
| author | rtkay123 <dev@kanjala.com> | 2026-02-03 13:45:46 +0200 |
|---|---|---|
| committer | rtkay123 <dev@kanjala.com> | 2026-02-03 13:45:46 +0200 |
| commit | eb2e86997d47249aa31b703598de13ab2eb96caa (patch) | |
| tree | 9a591adee7d027b305d07a04987b5559b99f4d37 /src/config | |
| parent | 0ea3cb1d4743b922fbc6e07037096e75caffba8f (diff) | |
| download | sellershut-eb2e86997d47249aa31b703598de13ab2eb96caa.tar.bz2 sellershut-eb2e86997d47249aa31b703598de13ab2eb96caa.zip | |
Diffstat (limited to 'src/config')
| -rw-r--r-- | src/config/cache.rs | 57 | ||||
| -rw-r--r-- | src/config/cli/cache/mod.rs | 46 | ||||
| -rw-r--r-- | src/config/cli/mod.rs (renamed from src/config/cli.rs) | 50 | ||||
| -rw-r--r-- | src/config/cli/oauth/mod.rs | 36 | ||||
| -rw-r--r-- | src/config/mod.rs | 35 |
5 files changed, 182 insertions, 42 deletions
diff --git a/src/config/cache.rs b/src/config/cache.rs new file mode 100644 index 0000000..96f3a9b --- /dev/null +++ b/src/config/cache.rs @@ -0,0 +1,57 @@ +use serde::Deserialize; +use url::Url; + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "lowercase")] +pub struct CacheConfig { + #[serde(rename = "dsn")] + pub redis_dsn: Url, + #[serde(default)] + pub pooled: bool, + #[serde(rename = "type")] + pub kind: RedisVariant, + #[serde(default = "default_max_conns")] + #[serde(rename = "max-connections")] + pub max_connections: u16, +} + +#[derive(Debug, Deserialize, Clone, Default)] +#[serde(rename_all = "kebab-case")] +pub enum RedisVariant { + Clustered, + #[default] + NonClustered, + Sentinel(SentinelConfig), +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq)] +pub struct SentinelConfig { + #[serde(rename = "sentinel_service_name")] + pub service_name: String, + #[serde(default)] + pub redis_tls_mode_secure: bool, + pub redis_db: Option<i64>, + pub redis_username: Option<String>, + pub redis_password: Option<String>, + #[serde(default)] + pub redis_use_resp3: bool, +} + +fn default_max_conns() -> u16 { + 100 +} + +fn default_cache() -> Url { + Url::parse("redis://localhost:6379").expect("valid default DATABASE url") +} + +impl Default for CacheConfig { + fn default() -> Self { + Self { + redis_dsn: default_cache(), + pooled: Default::default(), + kind: Default::default(), + max_connections: default_max_conns(), + } + } +} diff --git a/src/config/cli/cache/mod.rs b/src/config/cli/cache/mod.rs new file mode 100644 index 0000000..04b36bc --- /dev/null +++ b/src/config/cli/cache/mod.rs @@ -0,0 +1,46 @@ +use clap::{Parser, ValueEnum}; +use serde::Deserialize; +use url::Url; + +#[derive(Debug, Clone, Parser, Deserialize, Default)] +pub struct Cache { + /// Cache connection string + #[arg(long, env = "CACHE_URL", default_value = "redis://localhost:6379")] + pub cache_url: Option<Url>, + #[arg(long, env = "CACHE_POOL_ENABLED", default_value = "true")] + pub cache_pooled: Option<bool>, + #[serde(rename = "type")] + #[arg(long, env = "CACHE_TYPE", default_value = "non-clustered")] + pub cache_type: Option<RedisVariant>, + #[serde(default = "default_max_conns")] + #[serde(rename = "max-connections")] + #[arg(long, env = "CACHE_MAX_CONNECTIONS", default_value = "100")] + pub cache_max_conn: Option<u16>, + #[command(flatten)] + pub sentinel_config: SentinelConfig, +} + +#[derive(Debug, Deserialize, Clone, ValueEnum)] +#[serde(rename_all = "kebab-case")] +pub enum RedisVariant { + Clustered, + NonClustered, + Sentinel, +} + +fn default_max_conns() -> Option<u16> { + Some(100) +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Parser, Default)] +pub struct SentinelConfig { + #[serde(rename = "sentinel_service_name")] + #[arg(long, env = "CACHE_SENTINEL_NAME", default_value = "true")] + pub service_name: Option<String>, + #[serde(default)] + #[arg(long, env = "CACHE_TLS_MODE_SECURE")] + pub cache_tls_mode_secure: bool, + #[serde(default)] + #[arg(long, env = "CACHE_USE_RESP3")] + pub cache_use_resp3: bool, +} diff --git a/src/config/cli.rs b/src/config/cli/mod.rs index be1b913..81eb2fe 100644 --- a/src/config/cli.rs +++ b/src/config/cli/mod.rs @@ -1,9 +1,11 @@ +pub mod cache; + +#[cfg(feature = "oauth")] +pub mod oauth; + use std::path::PathBuf; use clap::Parser; -#[cfg(feature = "oauth-discord")] -use secrecy::SecretString; -use serde::Deserialize; use url::Url; use crate::config::{logging::LogLevel, port::port_in_range}; @@ -31,14 +33,17 @@ pub struct Cli { #[arg(short, long, env = "TIMEOUT_SECONDS", default_value = "10")] pub timeout_duration: Option<u64>, - /// Users database connection string + /// Database connection string #[arg( long, - env = "USERS_DATABASE_URL", + env = "DATABASE_URL", default_value = "postgres://postgres:password@localhost:5432/sellershut" )] pub db: Option<Url>, + #[command(flatten)] + pub cache: Option<cache::Cache>, + /// Server's system name #[arg(short, long, default_value = "sellershut", env = "SYSTEM_NAME")] pub system_name: Option<String>, @@ -50,37 +55,7 @@ pub struct Cli { /// Oauth optionas #[command(flatten)] #[cfg(feature = "oauth")] - pub oauth: OAuth, -} - -#[derive(Debug, Clone, Parser, Deserialize)] -pub struct OAuth { - #[cfg(feature = "oauth-discord")] - #[command(flatten)] - discord: DiscordOauth, - #[arg(long, env = "OAUTH_REDIRECT_URL")] - oauth_redirect_url: Option<Url>, -} - -#[cfg(feature = "oauth-discord")] -#[derive(Debug, Clone, Parser, Deserialize, Default)] -pub struct DiscordOauth { - #[arg(long, env = "OAUTH_DISCORD_CLIENT_ID")] - discord_client_id: Option<String>, - #[arg(long, env = "OAUTH_DISCORD_CLIENT_SECRET")] - discord_client_secret: Option<SecretString>, - #[arg( - long, - env = "OAUTH_DISCORD_TOKEN_URL", - default_value = "https://discord.com/api/oauth2/token" - )] - discord_token_url: Option<Url>, - #[arg( - long, - env = "OAUTH_DISCORD_AUTH_URL", - default_value = "https://discord.com/api/oauth2/authorize?response_type=code" - )] - discord_auth_url: Option<Url>, + pub oauth: oauth::OAuth, } #[cfg(test)] @@ -95,7 +70,8 @@ impl Default for Cli { domain: Default::default(), system_name: Default::default(), environment: Default::default(), - oauth: None, + oauth: Default::default(), + cache: Default::default(), db: url, } } diff --git a/src/config/cli/oauth/mod.rs b/src/config/cli/oauth/mod.rs new file mode 100644 index 0000000..4bf1c34 --- /dev/null +++ b/src/config/cli/oauth/mod.rs @@ -0,0 +1,36 @@ +use clap::Parser; +#[cfg(feature = "oauth-discord")] +use secrecy::SecretString; +use serde::Deserialize; +#[cfg(feature = "oauth")] +use url::Url; + +#[derive(Debug, Clone, Parser, Deserialize, Default)] +pub struct OAuth { + #[cfg(feature = "oauth-discord")] + #[command(flatten)] + discord: DiscordOauth, + #[arg(long, env = "OAUTH_REDIRECT_URL")] + oauth_redirect_url: Option<Url>, +} + +#[cfg(feature = "oauth-discord")] +#[derive(Debug, Clone, Parser, Deserialize, Default)] +pub struct DiscordOauth { + #[arg(long, env = "OAUTH_DISCORD_CLIENT_ID")] + discord_client_id: Option<String>, + #[arg(long, env = "OAUTH_DISCORD_CLIENT_SECRET")] + discord_client_secret: Option<SecretString>, + #[arg( + long, + env = "OAUTH_DISCORD_TOKEN_URL", + default_value = "https://discord.com/api/oauth2/token" + )] + discord_token_url: Option<Url>, + #[arg( + long, + env = "OAUTH_DISCORD_AUTH_URL", + default_value = "https://discord.com/api/oauth2/authorize?response_type=code" + )] + discord_auth_url: Option<Url>, +} diff --git a/src/config/mod.rs b/src/config/mod.rs index 7495b22..e64ae5c 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,13 +1,15 @@ +pub mod cache; mod cli; mod logging; mod port; pub use cli::Cli; -#[cfg(feature = "oauth")] -use secrecy::SecretString; use serde::Deserialize; use url::Url; -use crate::config::logging::LogLevel; +use crate::config::{ + cache::{CacheConfig, RedisVariant}, + logging::LogLevel, +}; #[derive(Default, Deserialize, Debug, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] @@ -23,6 +25,8 @@ pub struct Config { #[serde(default)] pub database: DatabaseOptions, #[serde(default)] + pub cache: CacheConfig, + #[serde(default)] pub server: Api, #[serde(default)] #[cfg(feature = "oauth")] @@ -65,7 +69,7 @@ pub struct OAuth { #[serde(rename_all = "kebab-case")] pub struct DiscordOauth { pub client_id: String, - pub client_secret: SecretString, + pub client_secret: secrecy::SecretString, #[serde(default = "discord_token_url")] pub token_url: Url, #[serde(default = "discord_auth_url")] @@ -94,7 +98,7 @@ impl Default for OAuth { #[cfg(feature = "oauth-discord")] discord: DiscordOauth { client_id: String::default(), - client_secret: SecretString::default(), + client_secret: secrecy::SecretString::default(), token_url: discord_token_url(), auth_url: discord_auth_url(), }, @@ -175,6 +179,7 @@ impl Config { pub fn merge_with_cli(&mut self, cli: &Cli) { let server = &mut self.server; let dsn = &mut self.database; + let cache = &mut self.cache; if let Some(port) = cli.port { server.port = port; @@ -195,6 +200,26 @@ impl Config { if let Some(db_url) = &cli.db { dsn.url = db_url.clone(); } + + if let Some(c) = cli.cache.as_ref().and_then(|v| v.cache_url.clone()) { + cache.redis_dsn = c; + } + + if let Some(c) = cli.cache.as_ref().and_then(|v| v.cache_pooled) { + cache.pooled = c; + } + + if let Some(c) = cli.cache.as_ref().and_then(|v| v.cache_max_conn) { + cache.max_connections = c; + } + + if let Some(c) = cli.cache.as_ref().and_then(|v| v.cache_type.clone()) { + cache.kind = match c { + cli::cache::RedisVariant::Clustered => RedisVariant::Clustered, + cli::cache::RedisVariant::NonClustered => RedisVariant::NonClustered, + cli::cache::RedisVariant::Sentinel => cache.kind.clone(), + }; + } } } |
