Skip to content

Commit c240a27

Browse files
feat: config inheriting
1 parent 7117529 commit c240a27

4 files changed

Lines changed: 58 additions & 5 deletions

File tree

configs/aggressive.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
inherits = "default.toml"
2+
3+
[rate_limiting]
4+
initial_ratelimit = 250
5+
ratelimit_thresholds = [
6+
[500, 1_000],
7+
[5_000, 2_500],
8+
[50_000, 10_000],
9+
[200_000, 50_000],
10+
[400_000, 100_000],
11+
]

configs/default.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ ratelimit_thresholds = [
3737
[300_000, 15_000], # NUM_ACCOUNTS * 12
3838
[350_000, 20_000], # NUM_ACCOUNTS * 14
3939
[400_000, 25_000], # NUM_ACCOUNTS * 16
40-
[450_000, 35_000], # NUM_ACCOUNTS * 18
41-
[550_000, 50_000], # NUM_ACCOUNTS * 22
42-
[600_000, 100_000], # NUM_ACCOUNTS * 24
4340
]
4441

4542
[workers]

crescendo/src/config.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::sync::OnceLock;
33

44
use serde::{Deserialize, Serialize};
55

6+
use crate::utils::merge_toml_values;
7+
68
/// Global configuration instance for the application.
79
static CONFIG_INSTANCE: OnceLock<Config> = OnceLock::new();
810

@@ -30,8 +32,29 @@ pub struct Config {
3032
impl Config {
3133
pub fn from_file(path: &PathBuf) -> Result<Self, Box<dyn std::error::Error>> {
3234
let config_str = std::fs::read_to_string(path)?;
33-
let config: Config = toml::from_str(&config_str)?;
34-
Ok(config)
35+
let mut config_value: toml::Value = toml::from_str(&config_str)?;
36+
37+
// Check if this config inherits from another.
38+
if let Some(inherits) = config_value.get("inherits").and_then(|v| v.as_str()) {
39+
// Load the inherited config recursively.
40+
let inherited_config = Self::from_file(&{
41+
if let Some(parent) = path.parent() {
42+
parent.join(inherits)
43+
} else {
44+
PathBuf::from(inherits)
45+
}
46+
})?;
47+
48+
// Merge the current config over the inherited one.
49+
config_value = merge_toml_values(toml::Value::try_from(inherited_config)?, config_value);
50+
}
51+
52+
// Remove the inherits field before deserializing.
53+
if let Some(table) = config_value.as_table_mut() {
54+
table.remove("inherits");
55+
}
56+
57+
Ok(config_value.try_into()?)
3558
}
3659
}
3760

crescendo/src/utils.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,25 @@ pub fn format_ranges(nums: &[usize]) -> String {
6969

7070
ranges.join(", ")
7171
}
72+
73+
/// Merge two TOML values, with `overlay` taking precedence over `base`.
74+
pub fn merge_toml_values(base: toml::Value, overlay: toml::Value) -> toml::Value {
75+
match (base, overlay) {
76+
(toml::Value::Table(mut base_table), toml::Value::Table(overlay_table)) => {
77+
for (key, overlay_value) in overlay_table {
78+
match base_table.get(&key) {
79+
Some(base_value) if base_value.is_table() && overlay_value.is_table() => {
80+
// Recursively merge nested tables
81+
base_table.insert(key, merge_toml_values(base_value.clone(), overlay_value));
82+
}
83+
_ => {
84+
// Replace the value
85+
base_table.insert(key, overlay_value);
86+
}
87+
}
88+
}
89+
toml::Value::Table(base_table)
90+
}
91+
(_, overlay) => overlay, // For non-table values, overlay completely replaces base.
92+
}
93+
}

0 commit comments

Comments
 (0)