zng_ext_config/
swap.rs
1use super::*;
2
3use crate::task::parking_lot::Mutex;
4use zng_var::VarHandle;
5
6pub struct SwapConfig {
10 cfg: Mutex<Box<dyn AnyConfig>>,
11 shared: ConfigVars,
12
13 source_status: BoxedVar<ConfigStatus>,
14 status: ArcVar<ConfigStatus>,
15 status_binding: VarHandle,
16}
17impl AnyConfig for SwapConfig {
18 fn get_raw(&mut self, key: ConfigKey, default: RawConfigValue, insert: bool, shared: bool) -> BoxedVar<RawConfigValue> {
19 if shared {
20 self.shared
21 .get_or_bind(key, |key| self.cfg.get_mut().get_raw(key.clone(), default, insert, false))
22 } else {
23 self.cfg.get_mut().get_raw(key, default, insert, false)
24 }
25 }
26
27 fn contains_key(&mut self, key: ConfigKey) -> BoxedVar<bool> {
28 self.shared
29 .get_or_bind_contains(key, |key| self.cfg.get_mut().contains_key(key.clone()))
30 }
31
32 fn status(&self) -> BoxedVar<ConfigStatus> {
33 self.status.read_only().boxed()
34 }
35
36 fn remove(&mut self, key: &ConfigKey) -> bool {
37 self.cfg.get_mut().remove(key)
38 }
39
40 fn low_memory(&mut self) {
41 self.cfg.get_mut().low_memory();
42 self.shared.low_memory();
43 }
44}
45impl Config for SwapConfig {
46 fn get<T: ConfigValue>(&mut self, key: impl Into<ConfigKey>, default: T, insert: bool) -> BoxedVar<T> {
47 self.shared.get_or_bind(key.into(), |key| {
48 self.cfg.get_mut().get_raw_serde_bidi(key.clone(), default, insert, false)
50 })
51 }
52}
53impl SwapConfig {
54 pub fn new() -> Self {
56 Self {
57 cfg: Mutex::new(Box::<MemoryConfig>::default()),
58 shared: ConfigVars::default(),
59 source_status: LocalVar(ConfigStatus::Loaded).boxed(),
60 status: var(ConfigStatus::Loaded),
61 status_binding: VarHandle::dummy(),
62 }
63 }
64
65 pub fn load(&mut self, cfg: impl AnyConfig) {
69 self.replace_source(Box::new(cfg))
70 }
71
72 fn replace_source(&mut self, source: Box<dyn AnyConfig>) {
73 self.source_status = source.status();
74 self.status.set_from(&self.source_status);
75 self.status_binding = self.source_status.bind(&self.status);
76
77 *self.cfg.get_mut() = source; self.shared.rebind(&mut **self.cfg.get_mut());
80 }
81}
82impl Default for SwapConfig {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use zng_app::APP;
91 use zng_ext_fs_watcher::FsWatcherManager;
92
93 use super::*;
94
95 #[test]
96 fn swap_config_in_memory() {
97 let mut app = APP
98 .minimal()
99 .extend(FsWatcherManager::default())
100 .extend(ConfigManager::default())
101 .run_headless(false);
102
103 let mut cfg = SwapConfig::new();
104
105 let v = cfg.get("key", true, false);
106 assert!(v.get());
107 v.set(false).unwrap();
108 app.update(false).assert_wait();
109
110 let v2 = cfg.get("key", true, false);
111 assert!(!v2.get() && !v.get());
112 assert_eq!(v.var_ptr(), v2.var_ptr());
113 }
114
115 #[test]
116 fn swap_config_swap() {
117 let mut app = APP
118 .minimal()
119 .extend(FsWatcherManager::default())
120 .extend(ConfigManager::default())
121 .run_headless(false);
122
123 let mut inner1 = MemoryConfig::default();
124 let c1 = inner1.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false, true);
125 c1.set(RawConfigValue::serialize(32).unwrap()).unwrap();
126 app.update(false).assert_wait();
127
128 let mut test = SwapConfig::new();
129 test.replace_source(Box::new(inner1));
130
131 let c1 = test.get("key", 0, false);
132
133 assert_eq!(32, c1.get());
134 }
135
136 #[test]
137 fn swap_config_swap_load() {
138 let mut app = APP
139 .minimal()
140 .extend(FsWatcherManager::default())
141 .extend(ConfigManager::default())
142 .run_headless(false);
143
144 let mut inner1 = MemoryConfig::default();
145 let inner_v1 = inner1.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false, true);
146 inner_v1.set(RawConfigValue::serialize(32).unwrap()).unwrap();
147 app.update(false).assert_wait();
148
149 let mut test = SwapConfig::new();
150 test.replace_source(Box::new(inner1));
151
152 let cfg = test.get("key", 0, false);
153
154 assert_eq!(32, cfg.get());
155
156 let mut inner2 = MemoryConfig::default();
157 let inner_v2 = inner2.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false, true);
158 inner_v2.set(RawConfigValue::serialize(42).unwrap()).unwrap();
159 app.update(false).assert_wait();
160
161 test.replace_source(Box::new(inner2));
162 app.update(false).assert_wait();
163
164 assert_eq!(42, cfg.get());
165 }
166
167 #[test]
168 fn swap_config_swap_load_delayed() {
169 let mut app = APP
170 .minimal()
171 .extend(FsWatcherManager::default())
172 .extend(ConfigManager::default())
173 .run_headless(false);
174
175 let mut inner1 = MemoryConfig::default();
176 let inner_v1 = inner1.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false, true);
177 inner_v1.set(RawConfigValue::serialize(32).unwrap()).unwrap();
178 app.update(false).assert_wait();
179
180 let mut test = SwapConfig::new();
181 test.replace_source(Box::new(inner1));
182
183 let cfg = test.get("key", 0, false);
184
185 assert_eq!(32, cfg.get());
186
187 let mut inner2 = MemoryConfig::default();
188 let inner_v2 = inner2.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false, true);
189 app.update(false).assert_wait();
190
191 test.replace_source(Box::new(inner2));
192 app.update(false).assert_wait();
193
194 assert_eq!(0, cfg.get());
195
196 inner_v2.set(RawConfigValue::serialize(42).unwrap()).unwrap();
197 app.update(false).assert_wait();
198 assert_eq!(42, cfg.get());
199 }
200
201 #[test]
202 fn swap_config_swap_fallback_delayed() {
203 let mut app = APP
204 .minimal()
205 .extend(FsWatcherManager::default())
206 .extend(ConfigManager::default())
207 .run_headless(false);
208
209 let mut fallback = MemoryConfig::default();
210 fallback
211 .get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false, true)
212 .set(RawConfigValue::serialize(100).unwrap())
213 .unwrap();
214
215 let mut inner1 = MemoryConfig::default();
216 let inner_v1 = inner1.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false, true);
217 inner_v1.set(RawConfigValue::serialize(32).unwrap()).unwrap();
218 app.update(false).assert_wait();
219
220 let mut test = SwapConfig::new();
221 test.replace_source(Box::new(FallbackConfig::new(inner1, fallback)));
222
223 let cfg = test.get("key", -1, false);
224
225 assert_eq!(32, cfg.get());
226
227 let mut fallback = MemoryConfig::default();
228 fallback
229 .get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false, true)
230 .set(RawConfigValue::serialize(100).unwrap())
231 .unwrap();
232 let mut inner2 = MemoryConfig::default();
233 let inner_v2 = inner2.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false, true);
234 app.update(false).assert_wait();
235
236 test.replace_source(Box::new(FallbackConfig::new(inner2, fallback)));
237 app.update(false).assert_wait();
238
239 assert_eq!(0, cfg.get());
240
241 inner_v2.set(RawConfigValue::serialize(42).unwrap()).unwrap();
242 app.update(false).assert_wait();
243 assert_eq!(42, cfg.get());
244 }
245}