Match handlers by object name and operation.
parent: tbd commit: 8bec189
Showing 1 changed file with 77 insertions and 43 deletions
giterated-stack/src/lib.rs
@@ -1,7 +1,7 @@ | ||
1 | 1 | pub mod handler; |
2 | 2 | pub mod state; |
3 | 3 | |
4 | use std::{future::Future, pin::Pin, sync::Arc}; | |
4 | use std::{collections::HashMap, future::Future, pin::Pin, str::FromStr, sync::Arc}; | |
5 | 5 | |
6 | 6 | use futures_util::FutureExt; |
7 | 7 | use giterated_models::{ |
@@ -9,17 +9,26 @@ use giterated_models::{ | ||
9 | 9 | instance::Instance, |
10 | 10 | object::{AnyObject, GiteratedObject, ObjectRequest, ObjectResponse}, |
11 | 11 | operation::{AnyOperation, GiteratedOperation}, |
12 | repository::Repository, | |
13 | user::User, | |
12 | 14 | }; |
15 | use tracing::info; | |
16 | ||
17 | #[derive(Clone, Debug, Hash, Eq, PartialEq)] | |
18 | struct ObjectOperationPair { | |
19 | object_name: String, | |
20 | operation_name: String, | |
21 | } | |
13 | 22 | |
14 | 23 | pub struct OperationHandlers<S: Send + Sync + Clone> { |
15 | operations: Vec<OperationWrapper<S>>, | |
24 | operations: HashMap<ObjectOperationPair, OperationWrapper<S>>, | |
16 | 25 | get_object: Vec<OperationWrapper<S>>, |
17 | 26 | } |
18 | 27 | |
19 | 28 | impl<S: Send + Sync + Clone> Default for OperationHandlers<S> { |
20 | 29 | fn default() -> Self { |
21 | 30 | Self { |
22 | operations: Vec::new(), | |
31 | operations: HashMap::new(), | |
23 | 32 | get_object: Vec::new(), |
24 | 33 | } |
25 | 34 | } |
@@ -34,11 +43,17 @@ impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> { | ||
34 | 43 | &mut self, |
35 | 44 | handler: H, |
36 | 45 | ) -> &mut Self { |
37 | let _operation_name = handler.operation_name().to_string(); | |
46 | let object_name = handler.object_name().to_string(); | |
47 | let operation_name = handler.operation_name().to_string(); | |
38 | 48 | |
39 | 49 | let wrapped = OperationWrapper::new(handler); |
40 | 50 | |
41 | self.operations.push(wrapped); | |
51 | let pair = ObjectOperationPair { | |
52 | object_name, | |
53 | operation_name, | |
54 | }; | |
55 | ||
56 | assert!(self.operations.insert(pair, wrapped).is_none()); | |
42 | 57 | |
43 | 58 | self |
44 | 59 | } |
@@ -65,29 +80,42 @@ impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> { | ||
65 | 80 | pub async fn handle<O: GiteratedObject>( |
66 | 81 | &self, |
67 | 82 | object: &O, |
68 | _operation_name: &str, | |
83 | operation_name: &str, | |
69 | 84 | operation: AnyOperation, |
70 | 85 | state: S, |
71 | 86 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { |
72 | for handler in self.operations.iter() { | |
73 | return match handler | |
87 | // TODO | |
88 | let object = object.to_string(); | |
89 | ||
90 | let object_name = { | |
91 | if User::from_str(&object).is_ok() { | |
92 | User::object_name() | |
93 | } else if Repository::from_str(&object).is_ok() { | |
94 | Repository::object_name() | |
95 | } else if Instance::from_str(&object).is_ok() { | |
96 | Instance::object_name() | |
97 | } else { | |
98 | return Err(OperationError::Unhandled); | |
99 | } | |
100 | } | |
101 | .to_string(); | |
102 | ||
103 | let target_handler = ObjectOperationPair { | |
104 | object_name, | |
105 | operation_name: operation_name.to_string(), | |
106 | }; | |
107 | ||
108 | if let Some(handler) = self.operations.get(&target_handler) { | |
109 | handler | |
74 | 110 | .handle( |
75 | 111 | AnyObject(object.to_string()), |
76 | 112 | operation.clone(), |
77 | 113 | state.clone(), |
78 | 114 | ) |
79 | 115 | .await |
80 | { | |
81 | Ok(ok) => Ok(ok), | |
82 | Err(err) => Err(match err { | |
83 | OperationError::Operation(err) => OperationError::Operation(err), | |
84 | OperationError::Internal(err) => OperationError::Internal(err), | |
85 | OperationError::Unhandled => continue, | |
86 | }), | |
87 | }; | |
116 | } else { | |
117 | Err(OperationError::Unhandled) | |
88 | 118 | } |
89 | ||
90 | Err(OperationError::Unhandled) | |
91 | 119 | } |
92 | 120 | |
93 | 121 | pub async fn resolve_object( |
@@ -166,8 +194,8 @@ where | ||
166 | 194 | } |
167 | 195 | } |
168 | 196 | |
169 | pub struct OperationWrapper<S: Send + Sync + Clone>( | |
170 | Box< | |
197 | pub struct OperationWrapper<S: Send + Sync + Clone> { | |
198 | func: Box< | |
171 | 199 | dyn Fn( |
172 | 200 | AnyObject, |
173 | 201 | AnyOperation, |
@@ -177,7 +205,8 @@ pub struct OperationWrapper<S: Send + Sync + Clone>( | ||
177 | 205 | + Send |
178 | 206 | + Sync, |
179 | 207 | >, |
180 | ); | |
208 | object_name: String, | |
209 | } | |
181 | 210 | |
182 | 211 | impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> { |
183 | 212 | pub fn new< |
@@ -188,28 +217,33 @@ impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> { | ||
188 | 217 | handler: F, |
189 | 218 | ) -> Self { |
190 | 219 | let handler = Arc::new(Box::pin(handler)); |
191 | Self(Box::new(move |any_object, any_operation, state| { | |
192 | let handler = handler.clone(); | |
193 | async move { | |
220 | Self { | |
221 | func: Box::new(move |any_object, any_operation, state| { | |
194 | 222 | let handler = handler.clone(); |
195 | let object: O = | |
196 | O::from_object_str(&any_object.0).map_err(|_| OperationError::Unhandled)?; | |
197 | let operation: D = serde_json::from_value(any_operation.0.clone()) | |
198 | .map_err(|_| OperationError::Unhandled)?; | |
199 | ||
200 | let result = handler.handle(&object, operation, state).await; | |
201 | result | |
202 | .map(|success| serde_json::to_vec(&success).unwrap()) | |
203 | .map_err(|err| match err { | |
204 | OperationError::Operation(err) => { | |
205 | OperationError::Operation(serde_json::to_vec(&err).unwrap()) | |
206 | } | |
207 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
208 | OperationError::Unhandled => OperationError::Unhandled, | |
209 | }) | |
210 | } | |
211 | .boxed() | |
212 | })) | |
223 | async move { | |
224 | let handler = handler.clone(); | |
225 | let object: O = | |
226 | O::from_object_str(&any_object.0).map_err(|_| OperationError::Unhandled)?; | |
227 | let operation: D = serde_json::from_value(any_operation.0.clone()) | |
228 | .map_err(|_| OperationError::Unhandled)?; | |
229 | ||
230 | let result = handler.handle(&object, operation, state).await; | |
231 | result | |
232 | .map(|success| serde_json::to_vec(&success).unwrap()) | |
233 | .map_err(|err| match err { | |
234 | OperationError::Operation(err) => { | |
235 | OperationError::Operation(serde_json::to_vec(&err).unwrap()) | |
236 | } | |
237 | OperationError::Internal(internal) => { | |
238 | OperationError::Internal(internal) | |
239 | } | |
240 | OperationError::Unhandled => OperationError::Unhandled, | |
241 | }) | |
242 | } | |
243 | .boxed() | |
244 | }), | |
245 | object_name: O::object_name().to_string(), | |
246 | } | |
213 | 247 | } |
214 | 248 | |
215 | 249 | async fn handle( |
@@ -218,6 +252,6 @@ impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> { | ||
218 | 252 | operation: AnyOperation, |
219 | 253 | state: S, |
220 | 254 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { |
221 | self.0(object, operation, state).await | |
255 | (self.func)(object, operation, state).await | |
222 | 256 | } |
223 | 257 | } |