Skip to main content

rullst_core/feature/
manager.rs

1#[cfg(feature = "orm")]
2use super::db::DbFeatureDriver;
3use super::driver::FeatureDriver;
4use super::env::EnvFeatureDriver;
5use super::memory::MemoryFeatureDriver;
6use super::toml::TomlFeatureDriver;
7
8// ─── Feature Manager & Facade ────────────────────────────────────────────────
9
10/// The primary feature flags manager coordinating the driver pipeline.
11#[non_exhaustive]
12pub struct FeatureManager {
13    drivers: Vec<Box<dyn FeatureDriver>>,
14}
15
16impl FeatureManager {
17    /// Creates a new `FeatureManager` with empty drivers.
18    pub fn new() -> Self {
19        Self {
20            drivers: Vec::new(),
21        }
22    }
23
24    /// Adds a driver to the evaluation pipeline.
25    pub fn add_driver(mut self, driver: Box<dyn FeatureDriver>) -> Self {
26        self.drivers.push(driver);
27        self
28    }
29
30    /// Check if a feature flag is enabled.
31    pub async fn enabled(&self, flag: &str) -> bool {
32        for driver in &self.drivers {
33            if let Some(val) = driver.enabled(flag).await {
34                return val;
35            }
36        }
37        false
38    }
39
40    /// Check if a feature flag is enabled for a target identifier.
41    pub async fn enabled_for(&self, flag: &str, identifier: &str) -> bool {
42        for driver in &self.drivers {
43            if let Some(val) = driver.enabled_for(flag, identifier).await {
44                return val;
45            }
46        }
47        false
48    }
49
50    /// Retrieve the variation name assigned to a target identifier.
51    pub async fn variant(&self, flag: &str, identifier: &str) -> Option<String> {
52        for driver in &self.drivers {
53            if let Some(val) = driver.variant(flag, identifier).await {
54                return Some(val);
55            }
56        }
57        None
58    }
59}
60
61impl Default for FeatureManager {
62    /// Creates a new `FeatureManager` with safe, batteries-included defaults:
63    /// 1. `MemoryFeatureDriver` (programmatic/testing overrides)
64    /// 2. `EnvFeatureDriver` (environment variable configuration)
65    /// 3. `TomlFeatureDriver` (local TOML file configuration via `Rullst.toml`)
66    /// 4. `DbFeatureDriver` when the `orm` feature is enabled (database-backed
67    ///    flags, requires an initialized database pool)
68    fn default() -> Self {
69        let manager = Self::new()
70            .add_driver(Box::new(MemoryFeatureDriver::new()))
71            .add_driver(Box::new(EnvFeatureDriver::new()))
72            .add_driver(Box::new(TomlFeatureDriver::new()));
73
74        #[cfg(feature = "orm")]
75        let manager = manager.add_driver(Box::new(DbFeatureDriver::new()));
76
77        manager
78    }
79}