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