1use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
13#[serde(tag = "type")]
14pub enum StorageConfig {
15 InMemory,
16 SlateDb(SlateDbStorageConfig),
17}
18
19impl Default for StorageConfig {
20 fn default() -> Self {
21 StorageConfig::SlateDb(SlateDbStorageConfig {
22 path: "data".to_string(),
23 object_store: ObjectStoreConfig::Local(LocalObjectStoreConfig {
24 path: ".data".to_string(),
25 }),
26 settings_path: None,
27 })
28 }
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
33pub struct SlateDbStorageConfig {
34 pub path: String,
36
37 pub object_store: ObjectStoreConfig,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
46 pub settings_path: Option<String>,
47}
48
49impl Default for SlateDbStorageConfig {
50 fn default() -> Self {
51 Self {
52 path: "data".to_string(),
53 object_store: ObjectStoreConfig::default(),
54 settings_path: None,
55 }
56 }
57}
58
59impl StorageConfig {
60 pub fn with_path_suffix(&self, suffix: &str) -> Self {
65 match self {
66 StorageConfig::InMemory => StorageConfig::InMemory,
67 StorageConfig::SlateDb(config) => StorageConfig::SlateDb(SlateDbStorageConfig {
68 path: format!("{}/{}", config.path, suffix),
69 object_store: config.object_store.clone(),
70 settings_path: config.settings_path.clone(),
71 }),
72 }
73 }
74}
75
76#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
78#[serde(tag = "type")]
79pub enum ObjectStoreConfig {
80 #[default]
82 InMemory,
83
84 Aws(AwsObjectStoreConfig),
86
87 Local(LocalObjectStoreConfig),
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
93pub struct AwsObjectStoreConfig {
94 pub region: String,
96
97 pub bucket: String,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
103pub struct LocalObjectStoreConfig {
104 pub path: String,
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn should_default_to_slatedb_with_local_data_dir() {
114 let config = StorageConfig::default();
116
117 match config {
119 StorageConfig::SlateDb(slate_config) => {
120 assert_eq!(slate_config.path, "data");
121 assert_eq!(
122 slate_config.object_store,
123 ObjectStoreConfig::Local(LocalObjectStoreConfig {
124 path: ".data".to_string()
125 })
126 );
127 }
128 _ => panic!("Expected SlateDb config as default"),
129 }
130 }
131
132 #[test]
133 fn should_deserialize_in_memory_config() {
134 let yaml = r#"type: InMemory"#;
136
137 let config: StorageConfig = serde_yaml::from_str(yaml).unwrap();
139
140 assert_eq!(config, StorageConfig::InMemory);
142 }
143
144 #[test]
145 fn should_deserialize_slatedb_config_with_local_object_store() {
146 let yaml = r#"
148type: SlateDb
149path: my-data
150object_store:
151 type: Local
152 path: /tmp/slatedb
153"#;
154
155 let config: StorageConfig = serde_yaml::from_str(yaml).unwrap();
157
158 match config {
160 StorageConfig::SlateDb(slate_config) => {
161 assert_eq!(slate_config.path, "my-data");
162 assert_eq!(
163 slate_config.object_store,
164 ObjectStoreConfig::Local(LocalObjectStoreConfig {
165 path: "/tmp/slatedb".to_string()
166 })
167 );
168 assert!(slate_config.settings_path.is_none());
169 }
170 _ => panic!("Expected SlateDb config"),
171 }
172 }
173
174 #[test]
175 fn should_deserialize_slatedb_config_with_aws_object_store() {
176 let yaml = r#"
178type: SlateDb
179path: my-data
180object_store:
181 type: Aws
182 region: us-west-2
183 bucket: my-bucket
184settings_path: slatedb.toml
185"#;
186
187 let config: StorageConfig = serde_yaml::from_str(yaml).unwrap();
189
190 match config {
192 StorageConfig::SlateDb(slate_config) => {
193 assert_eq!(slate_config.path, "my-data");
194 assert_eq!(
195 slate_config.object_store,
196 ObjectStoreConfig::Aws(AwsObjectStoreConfig {
197 region: "us-west-2".to_string(),
198 bucket: "my-bucket".to_string()
199 })
200 );
201 assert_eq!(slate_config.settings_path, Some("slatedb.toml".to_string()));
202 }
203 _ => panic!("Expected SlateDb config"),
204 }
205 }
206
207 #[test]
208 fn should_deserialize_slatedb_config_with_in_memory_object_store() {
209 let yaml = r#"
211type: SlateDb
212path: test-data
213object_store:
214 type: InMemory
215"#;
216
217 let config: StorageConfig = serde_yaml::from_str(yaml).unwrap();
219
220 match config {
222 StorageConfig::SlateDb(slate_config) => {
223 assert_eq!(slate_config.path, "test-data");
224 assert_eq!(slate_config.object_store, ObjectStoreConfig::InMemory);
225 }
226 _ => panic!("Expected SlateDb config"),
227 }
228 }
229
230 #[test]
231 fn should_serialize_slatedb_config() {
232 let config = StorageConfig::SlateDb(SlateDbStorageConfig {
234 path: "my-data".to_string(),
235 object_store: ObjectStoreConfig::Local(LocalObjectStoreConfig {
236 path: "/tmp/slatedb".to_string(),
237 }),
238 settings_path: None,
239 });
240
241 let yaml = serde_yaml::to_string(&config).unwrap();
243
244 assert!(yaml.contains("type: SlateDb"));
246 assert!(yaml.contains("path: my-data"));
247 assert!(yaml.contains("type: Local"));
248 assert!(!yaml.contains("settings_path"));
250 }
251}