JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Fixed imports!

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨ef0e853

⁨giterated-daemon/src/database_backend/handler.rs⁩ - ⁨8213⁩ bytes
Raw
1 use std::{collections::HashMap, pin::Pin, sync::Arc};
2
3 use futures_util::{future::BoxFuture, Future, FutureExt};
4 use giterated_models::{
5 error::{GetValueError, OperationError},
6 object::{AnyObject, GiteratedObject},
7 operation::{AnyOperation, GiteratedOperation},
8 repository::Repository,
9 settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError},
10 user::User,
11 value::{AnyValue, GetValue},
12 };
13
14 use super::DatabaseBackend;
15
16 #[async_trait::async_trait]
17 pub trait GiteratedOperationHandler<
18 O: GiteratedObject,
19 D: GiteratedOperation<O>,
20 S: Send + Sync + Clone,
21 >
22 {
23 fn operation_name(&self) -> &str;
24 fn object_name(&self) -> &str;
25
26 async fn handle(
27 &self,
28 object: &O,
29 operation: D,
30 state: S,
31 ) -> Result<D::Success, OperationError<D::Failure>>;
32 }
33
34 #[async_trait::async_trait]
35 impl<O, D, F, S> GiteratedOperationHandler<O, D, S> for F
36 where
37 F: FnMut(
38 &O,
39 D,
40 S,
41 ) -> Pin<
42 Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send>,
43 > + Send
44 + Sync
45 + Clone,
46 O: GiteratedObject + Send + Sync,
47 D: GiteratedOperation<O> + 'static,
48 <D as GiteratedOperation<O>>::Failure: Send,
49 S: Send + Sync + Clone + 'static,
50 {
51 fn operation_name(&self) -> &str {
52 D::operation_name()
53 }
54
55 fn object_name(&self) -> &str {
56 O::object_name()
57 }
58
59 async fn handle(
60 &self,
61 object: &O,
62 operation: D,
63 state: S,
64 ) -> Result<D::Success, OperationError<D::Failure>> {
65 self.clone()(object, operation, state).await
66 }
67 }
68
69 pub struct OperationWrapper<S: Send + Sync + Clone>(
70 Box<
71 dyn Fn(
72 AnyObject,
73 AnyOperation,
74 S,
75 )
76 -> Pin<Box<dyn Future<Output = Result<Vec<u8>, OperationError<Vec<u8>>>> + Send>>
77 + Send
78 + Sync,
79 >,
80 );
81
82 impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> {
83 pub fn new<
84 O: GiteratedObject + Send + Sync,
85 D: GiteratedOperation<O> + 'static,
86 F: GiteratedOperationHandler<O, D, S> + Send + Sync + 'static + Clone,
87 >(
88 handler: F,
89 ) -> Self {
90 let handler = Arc::new(Box::pin(handler));
91 Self(Box::new(move |any_object, any_operation, state| {
92 let handler = handler.clone();
93 async move {
94 let handler = handler.clone();
95 let object: O = O::from_object_str(&any_object.0).unwrap();
96 let operation: D = serde_json::from_value(any_operation.0.clone()).unwrap();
97
98 let result = handler.handle(&object, operation, state).await;
99 result
100 .map(|success| serde_json::to_vec(&success).unwrap())
101 .map_err(|err| match err {
102 OperationError::Operation(err) => {
103 OperationError::Operation(serde_json::to_vec(&err).unwrap())
104 }
105 OperationError::Internal(internal) => OperationError::Internal(internal),
106 OperationError::Unhandled => OperationError::Unhandled,
107 })
108 }
109 .boxed()
110 }))
111 }
112
113 async fn handle(
114 &mut self,
115 object: AnyObject,
116 operation: AnyOperation,
117 state: S,
118 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
119 self.0(object, operation, state).await
120 }
121 }
122
123 pub fn user_get_value(
124 object: &User,
125 operation: GetValue<AnyValue<User>>,
126 state: DatabaseBackend,
127 ) -> BoxFuture<'static, Result<AnyValue<User>, OperationError<GetValueError>>> {
128 let object = object.clone();
129
130 async move {
131 let mut user_backend = state.user_backend.lock().await;
132 let value = user_backend
133 .get_value(&object, &operation.value_name)
134 .await
135 .map_err(|e| OperationError::Internal(e.to_string()))?;
136
137 Ok(value)
138 }
139 .boxed()
140 }
141
142 pub fn user_get_setting(
143 object: &User,
144 operation: GetSetting<AnySetting>,
145 state: DatabaseBackend,
146 ) -> BoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
147 let object = object.clone();
148
149 async move {
150 let mut user_backend = state.user_backend.lock().await;
151 let value = user_backend
152 .get_setting(&object, &operation.setting_name)
153 .await
154 .map_err(|e| OperationError::Internal(e.to_string()))?;
155
156 Ok(value)
157 }
158 .boxed()
159 }
160
161 pub fn user_set_setting(
162 object: &User,
163 operation: SetSetting<AnySetting>,
164 state: DatabaseBackend,
165 ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> {
166 let object = object.clone();
167
168 async move {
169 let mut user_backend = state.user_backend.lock().await;
170 let value = user_backend
171 .write_setting(&object, &operation.setting_name, &operation.value.0)
172 .await
173 .map_err(|e| OperationError::Internal(e.to_string()))?;
174
175 Ok(value)
176 }
177 .boxed()
178 }
179
180 pub fn repository_get_value(
181 object: &Repository,
182 operation: GetValue<AnyValue<Repository>>,
183 state: DatabaseBackend,
184 ) -> BoxFuture<'static, Result<AnyValue<Repository>, OperationError<GetValueError>>> {
185 let object = object.clone();
186
187 async move {
188 let mut repository_backend = state.repository_backend.lock().await;
189 let value = repository_backend
190 .get_value(&object, &operation.value_name)
191 .await
192 .map_err(|e| OperationError::Internal(e.to_string()))?;
193
194 Ok(value)
195 }
196 .boxed()
197 }
198
199 pub fn repository_get_setting(
200 object: &Repository,
201 operation: GetSetting<AnySetting>,
202 state: DatabaseBackend,
203 ) -> BoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
204 let object = object.clone();
205
206 async move {
207 let mut repository_backend = state.repository_backend.lock().await;
208 let value = repository_backend
209 .get_setting(&object, &operation.setting_name)
210 .await
211 .map_err(|e| OperationError::Internal(e.to_string()))?;
212
213 Ok(value)
214 }
215 .boxed()
216 }
217
218 pub fn repository_set_setting(
219 object: &Repository,
220 operation: SetSetting<AnySetting>,
221 state: DatabaseBackend,
222 ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> {
223 let object = object.clone();
224
225 async move {
226 let mut repository_backend = state.repository_backend.lock().await;
227 let value = repository_backend
228 .write_setting(&object, &operation.setting_name, &operation.value.0)
229 .await
230 .map_err(|e| OperationError::Internal(e.to_string()))?;
231
232 Ok(value)
233 }
234 .boxed()
235 }
236
237 pub struct OperationHandlers<S: Send + Sync + Clone> {
238 operations: HashMap<String, OperationWrapper<S>>,
239 }
240
241 impl<S: Send + Sync + Clone> Default for OperationHandlers<S> {
242 fn default() -> Self {
243 Self {
244 operations: HashMap::new(),
245 }
246 }
247 }
248
249 impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> {
250 pub fn insert<
251 O: GiteratedObject + Send + Sync,
252 D: GiteratedOperation<O> + 'static,
253 H: GiteratedOperationHandler<O, D, S> + Send + Sync + 'static + Clone,
254 >(
255 &mut self,
256 handler: H,
257 ) -> &mut Self {
258 let operation_name = handler.operation_name().to_string();
259
260 let wrapped = OperationWrapper::new(handler);
261
262 self.operations.insert(operation_name, wrapped);
263
264 self
265 }
266
267 pub async fn handle<O: GiteratedObject>(
268 &mut self,
269 object: &O,
270 operation_name: &str,
271 operation: AnyOperation,
272 state: S,
273 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
274 if let Some(handler) = self.operations.get_mut(operation_name) {
275 handler
276 .handle(AnyObject(object.to_string()), operation, state)
277 .await
278 } else {
279 Err(OperationError::Internal(format!(
280 "unknown operation: {}",
281 operation_name
282 )))
283 }
284 }
285 }
286