Skip to main content

nodedb_lite/config/
governor.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Conversion from [`LiteConfig`] percentages to a shared [`nodedb_mem::GovernorConfig`].
4
5use nodedb_mem::{EngineId, EngineLimits, GovernorConfig};
6
7use super::types::LiteConfig;
8
9impl LiteConfig {
10    /// Build a [`GovernorConfig`] from this config's budget and percentages.
11    ///
12    /// Every `_percent` field maps to one [`EngineId`] Lite runs. `Wal` and
13    /// `Bridge` get a zero limit: Lite has no WAL crate and no cross-plane
14    /// bridge, so neither engine ever allocates here.
15    pub fn to_governor_config(&self) -> GovernorConfig {
16        let budget = self.memory_budget;
17        let pct = |percent: usize| budget * percent / 100;
18
19        let engine_limits = EngineLimits::zeroed()
20            .with(EngineId::Vector, pct(self.hnsw_percent))
21            .with(EngineId::Graph, pct(self.csr_percent))
22            .with(EngineId::Crdt, pct(self.loro_percent))
23            .with(EngineId::Query, pct(self.query_percent))
24            .with(EngineId::Kv, pct(self.kv_percent))
25            .with(EngineId::DocumentSchemaless, pct(self.document_percent))
26            .with(EngineId::DocumentStrict, pct(self.strict_percent))
27            .with(EngineId::Columnar, pct(self.columnar_percent))
28            .with(EngineId::Timeseries, pct(self.timeseries_percent))
29            .with(EngineId::Spatial, pct(self.spatial_percent))
30            .with(EngineId::Fts, pct(self.fts_percent))
31            .with(EngineId::Array, pct(self.array_percent))
32            .with(EngineId::Sparse, pct(self.sparse_percent));
33
34        GovernorConfig {
35            global_ceiling: budget,
36            engine_limits,
37        }
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn default_config_stays_under_the_global_ceiling() {
47        let cfg = LiteConfig::default();
48        let governor_config = cfg.to_governor_config();
49        assert!(governor_config.engine_limits.total() <= governor_config.global_ceiling);
50    }
51
52    #[test]
53    fn percentages_map_onto_the_matching_engine() {
54        let cfg = LiteConfig {
55            memory_budget: 1_000_000,
56            ..LiteConfig::default()
57        };
58        let governor_config = cfg.to_governor_config();
59        assert_eq!(
60            governor_config.engine_limits.get(EngineId::Vector),
61            1_000_000 * cfg.hnsw_percent / 100
62        );
63        assert_eq!(
64            governor_config.engine_limits.get(EngineId::Kv),
65            1_000_000 * cfg.kv_percent / 100
66        );
67        assert_eq!(governor_config.engine_limits.get(EngineId::Wal), 0);
68        assert_eq!(governor_config.engine_limits.get(EngineId::Bridge), 0);
69    }
70}