1use std::collections::HashMap;
2use std::net::IpAddr;
3use std::sync::Arc;
4
5use anyhow::Result;
6
7use async_trait::async_trait;
8
9pub use rapidquery::Expression;
10
11use serde::{Deserialize, Serialize};
12
13use crate::{BlobInfo, BlobInfoRequest, BlobMeta, ExpressionField, FieldValue, TaggedFieldValue};
14
15#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
16#[serde(deny_unknown_fields)]
17pub struct Hit {
18 pub id: String,
19 pub meta: BlobMeta,
20 pub url: String,
21}
22
23impl Hit {
24 pub fn new(id: String, meta: BlobMeta, url: String) -> Self {
25 Self { id, meta, url }
26 }
27}
28
29#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
30#[serde(deny_unknown_fields)]
31pub struct FacetResponse {
32 pub tags: HashMap<String, u64>,
33 pub meta: HashMap<String, HashMap<FieldValue, u64>>,
34}
35
36#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
38#[serde(deny_unknown_fields)]
39pub struct QueryResponse {
40 pub count: usize,
42
43 pub total: usize,
45
46 pub hits: Vec<Hit>,
48
49 pub facets: Option<FacetResponse>,
53}
54
55#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
56pub enum RedirectInfo {
57 Automatic {
58 public_address: IpAddr,
59 local_address: IpAddr,
60 subnet_mask: IpAddr,
61 },
62 Static {
63 static_address: IpAddr,
64 },
65}
66
67#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
68#[serde(deny_unknown_fields)]
69pub struct StorageNodeInfo {
70 pub id: String,
71 pub redirect_info: RedirectInfo,
72 pub port: u16,
73 pub size: u64,
74 pub available_space: u64,
75}
76
77#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
79#[serde(deny_unknown_fields)]
80pub struct StorageNodeResponseData {
81 pub rebuild_requested: bool,
82}
83
84#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
85#[serde(deny_unknown_fields)]
86pub struct MetadataList {
87 pub tags: HashMap<String, usize>,
88 pub fields: HashMap<String, HashMap<FieldValue, usize>>,
89}
90
91#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
93#[serde(rename_all = "snake_case")]
94pub enum SortOrder {
95 CreationAscending,
96 CreationDescending,
97}
98
99#[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
101#[serde(deny_unknown_fields)]
102pub struct Query {
103 pub expression: Expression<ExpressionField>,
105 pub from: usize,
106 pub size: usize,
107 pub sign_urls: bool,
108 pub facets: bool,
109 pub sort_order: SortOrder,
111}
112
113impl Query {
114 pub fn with_expression<S: Into<String>>(mut self, expression: S) -> Result<Self> {
115 self.expression = Expression::parse(expression.into())?;
116 Ok(self)
117 }
118
119 #[must_use]
120 pub fn and_tag<S: Into<String>>(mut self, tag: S) -> Self {
121 let new_expr = Expression::Field(ExpressionField::Tag { tag: tag.into() });
122 self.expression = Expression::And {
123 and: (Box::from(self.expression), Box::from(new_expr)),
124 };
125 self
126 }
127
128 #[must_use]
129 pub fn and_field<K: Into<String>, V: Into<FieldValue>>(mut self, k: K, v: V) -> Self {
130 let new_expr = Expression::Field(ExpressionField::Field {
131 key: k.into(),
132 value: v.into(),
133 });
134 self.expression = Expression::And {
135 and: (Box::from(self.expression), Box::from(new_expr)),
136 };
137 self
138 }
139
140 #[must_use]
141 pub fn with_from(mut self, f: usize) -> Self {
142 self.from = f;
143 self
144 }
145
146 #[must_use]
147 pub fn with_size(mut self, s: usize) -> Self {
148 self.size = s;
149 self
150 }
151
152 #[must_use]
153 pub fn with_facets(mut self, f: bool) -> Self {
154 self.facets = f;
155 self
156 }
157
158 pub fn with_sort_order(mut self, sort_order: SortOrder) -> Self {
159 self.sort_order = sort_order;
160 self
161 }
162}
163
164impl Default for Query {
165 fn default() -> Self {
166 Query {
167 expression: Default::default(),
168 from: 0,
169 size: 30,
170 sign_urls: true,
171 facets: false,
172 sort_order: SortOrder::CreationAscending,
173 }
174 }
175}
176
177#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
178#[serde(deny_unknown_fields)]
179pub struct RoutingConfig {
180 pub routing_key: String,
182
183 pub routes: HashMap<FieldValue, String>,
185}
186
187impl RoutingConfig {
188 pub fn new<S: Into<String>>(key: S) -> Self {
189 Self {
190 routing_key: key.into(),
191 routes: HashMap::new(),
192 }
193 }
194
195 #[must_use]
196 pub fn with_route<K: Into<FieldValue>, V: Into<String>>(
197 mut self,
198 field_value: K,
199 storage_node_id: V,
200 ) -> Self {
201 self.routes
202 .insert(field_value.into(), storage_node_id.into());
203 self
204 }
205}
206
207#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
208#[serde(deny_unknown_fields)]
209pub struct TaggedRoutingConfig {
210 pub routing_key: String,
212
213 pub routes: HashMap<TaggedFieldValue, String>,
215}
216
217impl From<RoutingConfig> for TaggedRoutingConfig {
218 fn from(v: RoutingConfig) -> Self {
219 Self {
220 routing_key: v.routing_key,
221 routes: v
222 .routes
223 .into_iter()
224 .map(|(k, v)| (k.into(), v))
225 .collect::<HashMap<_, _>>(),
226 }
227 }
228}
229
230impl From<TaggedRoutingConfig> for RoutingConfig {
231 fn from(v: TaggedRoutingConfig) -> Self {
232 Self {
233 routing_key: v.routing_key,
234 routes: v
235 .routes
236 .into_iter()
237 .map(|(k, v)| (k.into(), v))
238 .collect::<HashMap<_, _>>(),
239 }
240 }
241}
242
243#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
244pub enum DirtyState {
245 Dirty,
246 Clean,
247}
248
249#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
250#[serde(deny_unknown_fields)]
251pub struct RoutingConfigState {
252 pub routing_config: RoutingConfig,
253 pub state: DirtyState,
254}
255
256#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
257#[serde(deny_unknown_fields)]
258pub struct TaggedRoutingConfigState {
259 pub routing_config: TaggedRoutingConfig,
260 pub state: DirtyState,
261}
262
263impl From<RoutingConfigState> for TaggedRoutingConfigState {
264 fn from(v: RoutingConfigState) -> Self {
265 Self {
266 routing_config: v.routing_config.into(),
267 state: v.state,
268 }
269 }
270}
271
272impl From<TaggedRoutingConfigState> for RoutingConfigState {
273 fn from(v: TaggedRoutingConfigState) -> Self {
274 Self {
275 routing_config: v.routing_config.into(),
276 state: v.state,
277 }
278 }
279}
280
281#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
282#[serde(deny_unknown_fields)]
283pub struct MoveInformation {
284 pub blob_id: String,
285 pub owner_username: String,
286 pub destination_node: StorageNodeInfo,
287}
288
289#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
290#[serde(rename_all = "snake_case")]
291pub enum RoutingAlgorithm {
292 RoundRobin,
293 MinSize,
294}
295
296#[async_trait]
297pub trait BlobIndexer {
298 async fn pick_node_for_blob(
299 &self,
300 blob_id: &str,
301 info_request: BlobInfoRequest,
302 ) -> Result<StorageNodeInfo>;
303 async fn get_blob_meta(&self, blob_id: &str, user: &str) -> Result<Option<BlobInfo>>;
304 async fn index_blob(&self, blob_id: &str, meta: BlobInfo, storage_node_id: &str) -> Result<()>;
305 async fn delete_blob(&self, blob_id: &str, username: &str) -> Result<Option<StorageNodeInfo>>;
306 async fn get_blob_storage_node(&self, blob_id: &str) -> Result<Option<StorageNodeInfo>>;
307 async fn clear(&self) -> Result<()>;
308 async fn flush(&self) -> Result<()>;
309}
310
311#[async_trait]
312pub trait RoutingConfigManager {
313 async fn get_routing_config(&self, user: &str) -> Result<Option<RoutingConfig>>;
314 async fn set_routing_config(&self, user: &str, config: &RoutingConfig) -> Result<()>;
315 async fn delete_routing_config(&self, user: &str) -> Result<()>;
316
317 async fn get_move_requests(&self, src_node: &str) -> Result<Vec<MoveInformation>>;
318
319 async fn flush(&self) -> Result<()>;
320}
321
322#[async_trait]
323pub trait NodeAdminController {
324 async fn register_storage_node(&self, def: StorageNodeInfo) -> Result<StorageNodeResponseData>;
325 async fn list_storage_nodes(&self) -> Result<Vec<StorageNodeInfo>>;
326
327 async fn start_rebuild(&self) -> Result<()>;
328 async fn rebuild_complete(&self, storage_node_id: &str) -> Result<()>;
329 async fn flush(&self) -> Result<()>;
330}
331
332#[async_trait]
333pub trait UserManagement {
334 async fn login(&self, user: &str, password: &str) -> Result<bool>;
335 async fn register(&self, user: &str, password: &str) -> Result<()>;
336 async fn has_user(&self, user: &str) -> Result<bool>;
337 async fn list(&self) -> Result<Vec<String>>;
338 async fn flush(&self) -> Result<()>;
339}
340
341#[async_trait]
342pub trait QueryExecutor {
343 async fn query(&self, q: &Query, username: &str) -> Result<QueryResponse>;
344 async fn query_move_requests(
345 &self,
346 query: &Query,
347 username: &str,
348 src_node: &str,
349 ) -> Result<Vec<String>>;
350 async fn list_metadata(
351 &self,
352 tags: Option<Vec<String>>,
353 meta_keys: Option<Vec<String>>,
354 username: &str,
355 ) -> Result<MetadataList>;
356}
357
358#[async_trait]
359pub trait DirectoryNode {
360 fn indexer(&self) -> Arc<dyn BlobIndexer + Send + Sync>;
361 fn routing(&self) -> Arc<dyn RoutingConfigManager + Send + Sync>;
362 fn admin(&self) -> Arc<dyn NodeAdminController + Send + Sync>;
363 fn user(&self) -> Arc<dyn UserManagement + Send + Sync>;
364 fn query(&self) -> Arc<dyn QueryExecutor + Send + Sync>;
365
366 async fn flush(&self) -> Result<()>;
367}
368
369pub type DynDirectoryNode = Arc<dyn DirectoryNode + Send + Sync>;