radicle/config/node: Granular Default Values

Provide default values not only per struct, but for each individual
struct member. This allows more granular configuration and fallback to
defaults.
This commit is contained in:
Lorenz Leutgeb 2025-08-12 15:49:12 +02:00
parent 77f63c76df
commit c4ff0d8eae
1 changed files with 133 additions and 25 deletions

View File

@ -15,9 +15,6 @@ use crate::node::{Address, Alias, NodeId};
/// Peer-to-peer protocol version. /// Peer-to-peer protocol version.
pub type ProtocolVersion = u8; pub type ProtocolVersion = u8;
/// Default number of workers to spawn.
pub const DEFAULT_WORKERS: usize = 8;
/// Configured public seeds. /// Configured public seeds.
pub mod seeds { pub mod seeds {
use std::{ use std::{
@ -128,31 +125,47 @@ impl Network {
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct Limits { pub struct Limits {
/// Number of routing table entries before we start pruning. /// Number of routing table entries before we start pruning.
#[serde(default = "defaults::limit_routing_max_size")]
pub routing_max_size: usize, pub routing_max_size: usize,
/// How long to keep a routing table entry before being pruned. /// How long to keep a routing table entry before being pruned.
#[serde(with = "crate::serde_ext::localtime::duration")] #[serde(
default = "defaults::limit_routing_max_age",
with = "crate::serde_ext::localtime::duration"
)]
#[cfg_attr( #[cfg_attr(
feature = "schemars", feature = "schemars",
schemars(with = "crate::schemars_ext::localtime::LocalDuration") schemars(with = "crate::schemars_ext::localtime::LocalDuration")
)] )]
pub routing_max_age: LocalDuration, pub routing_max_age: LocalDuration,
/// How long to keep a gossip message entry before pruning it. /// How long to keep a gossip message entry before pruning it.
#[serde(with = "crate::serde_ext::localtime::duration")] #[serde(
default = "defaults::limit_gossip_max_age",
with = "crate::serde_ext::localtime::duration"
)]
#[cfg_attr( #[cfg_attr(
feature = "schemars", feature = "schemars",
schemars(with = "crate::schemars_ext::localtime::LocalDuration") schemars(with = "crate::schemars_ext::localtime::LocalDuration")
)] )]
pub gossip_max_age: LocalDuration, pub gossip_max_age: LocalDuration,
/// Maximum number of concurrent fetches per peer connection. /// Maximum number of concurrent fetches per peer connection.
#[serde(default = "defaults::limit_fetch_concurrency")]
pub fetch_concurrency: usize, pub fetch_concurrency: usize,
/// Maximum number of open files. /// Maximum number of open files.
#[serde(default = "defaults::limit_max_open_files")]
pub max_open_files: usize, pub max_open_files: usize,
/// Rate limitter settings. /// Rate limitter settings.
#[serde(default)] #[serde(default)]
pub rate: RateLimits, pub rate: RateLimits,
/// Connection limits. /// Connection limits.
#[serde(default)] #[serde(default)]
pub connection: ConnectionLimits, pub connection: ConnectionLimits,
/// Channel limits. /// Channel limits.
#[serde(default)] #[serde(default)]
pub fetch_pack_receive: FetchPackSizeLimit, pub fetch_pack_receive: FetchPackSizeLimit,
@ -161,11 +174,11 @@ pub struct Limits {
impl Default for Limits { impl Default for Limits {
fn default() -> Self { fn default() -> Self {
Self { Self {
routing_max_size: 1000, routing_max_size: defaults::limit_routing_max_size(),
routing_max_age: LocalDuration::from_mins(7 * 24 * 60), // One week routing_max_age: defaults::limit_routing_max_age(),
gossip_max_age: LocalDuration::from_mins(2 * 7 * 24 * 60), // Two weeks gossip_max_age: defaults::limit_gossip_max_age(),
fetch_concurrency: 1, fetch_concurrency: defaults::limit_fetch_concurrency(),
max_open_files: 4096, max_open_files: defaults::limit_max_open_files(),
rate: RateLimits::default(), rate: RateLimits::default(),
connection: ConnectionLimits::default(), connection: ConnectionLimits::default(),
fetch_pack_receive: FetchPackSizeLimit::default(), fetch_pack_receive: FetchPackSizeLimit::default(),
@ -269,16 +282,19 @@ impl Default for FetchPackSizeLimit {
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct ConnectionLimits { pub struct ConnectionLimits {
/// Max inbound connections. /// Max inbound connections.
#[serde(default = "defaults::limit_connections_inbound")]
pub inbound: usize, pub inbound: usize,
/// Max outbound connections. Note that this can be higher than the *target* number. /// Max outbound connections. Note that this can be higher than the *target* number.
#[serde(default = "defaults::limit_connections_outbound")]
pub outbound: usize, pub outbound: usize,
} }
impl Default for ConnectionLimits { impl Default for ConnectionLimits {
fn default() -> Self { fn default() -> Self {
Self { Self {
inbound: 128, inbound: defaults::limit_connections_inbound(),
outbound: 16, outbound: defaults::limit_connections_outbound(),
} }
} }
} }
@ -297,21 +313,18 @@ pub struct RateLimit {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct RateLimits { pub struct RateLimits {
#[serde(default = "defaults::limit_rate_inbound")]
pub inbound: RateLimit, pub inbound: RateLimit,
#[serde(default = "defaults::limit_rate_outbound")]
pub outbound: RateLimit, pub outbound: RateLimit,
} }
impl Default for RateLimits { impl Default for RateLimits {
fn default() -> Self { fn default() -> Self {
Self { Self {
inbound: RateLimit { inbound: defaults::limit_rate_inbound(),
fill_rate: 5.0, outbound: defaults::limit_rate_outbound(),
capacity: 1024,
},
outbound: RateLimit {
fill_rate: 10.0,
capacity: 2048,
},
} }
} }
} }
@ -536,7 +549,7 @@ impl Config {
onion: None, onion: None,
relay: Relay::default(), relay: Relay::default(),
limits: Limits::default(), limits: Limits::default(),
workers: DEFAULT_WORKERS, workers: defaults::workers(),
log: defaults::log(), log: defaults::log(),
seeding_policy: DefaultSeedingPolicy::default(), seeding_policy: DefaultSeedingPolicy::default(),
extra: json::Map::default(), extra: json::Map::default(),
@ -576,13 +589,108 @@ impl Config {
/// Defaults as functions, for serde. /// Defaults as functions, for serde.
mod defaults { mod defaults {
/// Worker count. /// Default number of workers to spawn.
pub fn workers() -> usize { #[inline]
super::DEFAULT_WORKERS pub const fn workers() -> usize {
8
} }
/// Log level. /// Log level.
pub fn log() -> log::Level { #[inline]
pub const fn log() -> log::Level {
log::Level::Info log::Level::Info
} }
#[inline]
pub const fn limit_connections_inbound() -> usize {
128
}
#[inline]
pub const fn limit_connections_outbound() -> usize {
16
}
#[inline]
pub const fn limit_routing_max_size() -> usize {
1000
}
#[inline]
pub const fn limit_routing_max_age() -> localtime::LocalDuration {
localtime::LocalDuration::from_mins(7 * 24 * 60) // One week
}
#[inline]
pub const fn limit_gossip_max_age() -> localtime::LocalDuration {
localtime::LocalDuration::from_mins(2 * 7 * 24 * 60) // Two weeks
}
#[inline]
pub const fn limit_fetch_concurrency() -> usize {
1
}
#[inline]
pub const fn limit_max_open_files() -> usize {
4096
}
#[inline]
pub const fn limit_rate_inbound() -> super::RateLimit {
super::RateLimit {
fill_rate: 5.0,
capacity: 1024,
}
}
#[inline]
pub const fn limit_rate_outbound() -> super::RateLimit {
super::RateLimit {
fill_rate: 10.0,
capacity: 2048,
}
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod test {
#[test]
fn partial() {
use super::Config;
use serde_json::json;
let config: Config = serde_json::from_value(json!({
"alias": "example",
"limits": {
"connection": {
"inbound": 1337,
},
},
}
))
.unwrap();
assert_eq!(config.limits.connection.inbound, 1337);
assert_eq!(
config.limits.connection.outbound,
super::defaults::limit_connections_outbound()
);
let config: Config = serde_json::from_value(json!({
"alias": "example",
"limits": {
"connection": {
"outbound": 1337,
},
},
}
))
.unwrap();
assert_eq!(
config.limits.connection.inbound,
super::defaults::limit_connections_inbound()
);
assert_eq!(config.limits.connection.outbound, 1337);
}
} }