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