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
80 use super::*;
81
82 #[test]
83 fn swap_config_in_memory() {
84 let mut app = APP.minimal().run_headless(false);
85
86 let mut cfg = SwapConfig::new();
87
88 let raw_true = RawConfigValue::serialize(true).unwrap();
89 let raw_false = RawConfigValue::serialize(false).unwrap();
90
91 let v = cfg.get_raw("key".into(), raw_true.clone(), false);
92 assert_eq!(v.get(), raw_true);
93 v.set(raw_false.clone());
94 app.update(false).assert_wait();
95
96 let v2 = cfg.get_raw("key".into(), raw_true, false);
97 assert!(v2.get() == raw_false && v.get() == raw_false);
98 assert!(v.var_eq(&v2));
99 }
100
101 #[test]
102 fn swap_config_swap() {
103 let mut app = APP.minimal().run_headless(false);
104
105 let mut inner1 = MemoryConfig::default();
106 let c1 = inner1.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false);
107 c1.set(RawConfigValue::serialize(32).unwrap());
108 app.update(false).assert_wait();
109
110 let mut test = SwapConfig::new();
111 test.replace_source(Box::new(inner1));
112
113 let c1 = test.get("key", 0, false);
114
115 assert_eq!(32, c1.get());
116 }
117
118 #[test]
119 fn swap_config_swap_load() {
120 let mut app = APP.minimal().run_headless(false);
121
122 let mut inner1 = MemoryConfig::default();
123 let inner_v1 = inner1.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false);
124 inner_v1.set(RawConfigValue::serialize(32).unwrap());
125 app.update(false).assert_wait();
126
127 let mut test = SwapConfig::new();
128 test.replace_source(Box::new(inner1));
129
130 let cfg = test.get("key", 0, false);
131
132 assert_eq!(32, cfg.get());
133
134 let mut inner2 = MemoryConfig::default();
135 let inner_v2 = inner2.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false);
136 inner_v2.set(RawConfigValue::serialize(42).unwrap());
137 app.update(false).assert_wait();
138
139 test.replace_source(Box::new(inner2));
140 app.update(false).assert_wait();
141
142 assert_eq!(42, cfg.get());
143 }
144
145 #[test]
146 fn swap_config_swap_load_delayed() {
147 let mut app = APP.minimal().run_headless(false);
148
149 let mut inner1 = MemoryConfig::default();
150 let inner_v1 = inner1.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false);
151 inner_v1.set(RawConfigValue::serialize(32).unwrap());
152 app.update(false).assert_wait();
153
154 let mut test = SwapConfig::new();
155 test.replace_source(Box::new(inner1));
156
157 let cfg = test.get("key", 0, false);
158
159 assert_eq!(32, cfg.get());
160
161 let mut inner2 = MemoryConfig::default();
162 let inner_v2 = inner2.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false);
163 app.update(false).assert_wait();
164
165 test.replace_source(Box::new(inner2));
166 app.update(false).assert_wait();
167
168 assert_eq!(0, cfg.get());
169
170 inner_v2.set(RawConfigValue::serialize(42).unwrap());
171 app.update(false).assert_wait();
172 assert_eq!(42, cfg.get());
173 }
174
175 #[test]
176 fn swap_config_swap_fallback_delayed() {
177 let mut app = APP.minimal().run_headless(false);
178
179 let mut fallback = MemoryConfig::default();
180 fallback
181 .get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false)
182 .set(RawConfigValue::serialize(100).unwrap());
183
184 let mut inner1 = MemoryConfig::default();
185 let inner_v1 = inner1.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false);
186 inner_v1.set(RawConfigValue::serialize(32).unwrap());
187 app.update(false).assert_wait();
188
189 let mut test = SwapConfig::new();
190 test.replace_source(Box::new(FallbackConfig::new(inner1, fallback)));
191
192 let cfg = test.get("key", -1, false);
193
194 assert_eq!(32, cfg.get());
195
196 let mut fallback = MemoryConfig::default();
197 fallback
198 .get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false)
199 .set(RawConfigValue::serialize(100).unwrap());
200 let mut inner2 = MemoryConfig::default();
201 let inner_v2 = inner2.get_raw("key".into(), RawConfigValue::serialize(0).unwrap(), false);
202 app.update(false).assert_wait();
203
204 test.replace_source(Box::new(FallbackConfig::new(inner2, fallback)));
205 app.update(false).assert_wait();
206
207 assert_eq!(0, cfg.get());
208
209 inner_v2.set(RawConfigValue::serialize(42).unwrap());
210 app.update(false).assert_wait();
211 assert_eq!(42, cfg.get());
212 }
213}