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

ambee/giterated

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

Match handlers by object name and operation.

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨8bec189

⁨giterated-stack/src/lib.rs⁩ - ⁨7435⁩ bytes
Raw
1 pub mod handler;
2 pub mod state;
3
4 use std::{collections::HashMap, future::Future, pin::Pin, str::FromStr, sync::Arc};
5
6 use futures_util::FutureExt;
7 use giterated_models::{
8 error::OperationError,
9 instance::Instance,
10 object::{AnyObject, GiteratedObject, ObjectRequest, ObjectResponse},
11 operation::{AnyOperation, GiteratedOperation},
12 repository::Repository,
13 user::User,
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 }
22
23 pub struct OperationHandlers<S: Send + Sync + Clone> {
24 operations: HashMap<ObjectOperationPair, OperationWrapper<S>>,
25 get_object: Vec<OperationWrapper<S>>,
26 }
27
28 impl<S: Send + Sync + Clone> Default for OperationHandlers<S> {
29 fn default() -> Self {
30 Self {
31 operations: HashMap::new(),
32 get_object: Vec::new(),
33 }
34 }
35 }
36
37 impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> {
38 pub fn insert<
39 O: GiteratedObject + Send + Sync,
40 D: GiteratedOperation<O> + 'static,
41 H: GiteratedOperationHandler<O, D, S> + Send + Sync + 'static + Clone,
42 >(
43 &mut self,
44 handler: H,
45 ) -> &mut Self {
46 let object_name = handler.object_name().to_string();
47 let operation_name = handler.operation_name().to_string();
48
49 let wrapped = OperationWrapper::new(handler);
50
51 let pair = ObjectOperationPair {
52 object_name,
53 operation_name,
54 };
55
56 assert!(self.operations.insert(pair, wrapped).is_none());
57
58 self
59 }
60
61 pub fn register_object<O: GiteratedObject + Send + Sync>(&mut self) -> &mut Self {
62 let closure = |_: &Instance, operation: ObjectRequest, _state| {
63 async move {
64 if O::from_str(&operation.0).is_ok() {
65 Ok(ObjectResponse(operation.0))
66 } else {
67 Err(OperationError::Unhandled)
68 }
69 }
70 .boxed()
71 };
72
73 let wrapped = OperationWrapper::new(closure);
74
75 self.get_object.push(wrapped);
76
77 self
78 }
79
80 pub async fn handle<O: GiteratedObject>(
81 &self,
82 object: &O,
83 operation_name: &str,
84 operation: AnyOperation,
85 state: S,
86 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
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
110 .handle(
111 AnyObject(object.to_string()),
112 operation.clone(),
113 state.clone(),
114 )
115 .await
116 } else {
117 Err(OperationError::Unhandled)
118 }
119 }
120
121 pub async fn resolve_object(
122 &self,
123 instance: AnyObject,
124 request: ObjectRequest,
125 state: S,
126 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
127 for handler in self.get_object.iter() {
128 if let Ok(response) = handler
129 .handle(
130 instance.clone(),
131 AnyOperation(serde_json::to_value(request.clone()).unwrap()),
132 state.clone(),
133 )
134 .await
135 {
136 return Ok(response);
137 }
138 }
139
140 Err(OperationError::Unhandled)
141 }
142 }
143
144 #[async_trait::async_trait]
145 pub trait GiteratedOperationHandler<
146 O: GiteratedObject,
147 D: GiteratedOperation<O>,
148 S: Send + Sync + Clone,
149 >
150 {
151 fn operation_name(&self) -> &str;
152 fn object_name(&self) -> &str;
153
154 async fn handle(
155 &self,
156 object: &O,
157 operation: D,
158 state: S,
159 ) -> Result<D::Success, OperationError<D::Failure>>;
160 }
161
162 #[async_trait::async_trait]
163 impl<O, D, F, S> GiteratedOperationHandler<O, D, S> for F
164 where
165 F: FnMut(
166 &O,
167 D,
168 S,
169 ) -> Pin<
170 Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send>,
171 > + Send
172 + Sync
173 + Clone,
174 O: GiteratedObject + Send + Sync,
175 D: GiteratedOperation<O> + 'static,
176 <D as GiteratedOperation<O>>::Failure: Send,
177 S: Send + Sync + Clone + 'static,
178 {
179 fn operation_name(&self) -> &str {
180 D::operation_name()
181 }
182
183 fn object_name(&self) -> &str {
184 O::object_name()
185 }
186
187 async fn handle(
188 &self,
189 object: &O,
190 operation: D,
191 state: S,
192 ) -> Result<D::Success, OperationError<D::Failure>> {
193 self.clone()(object, operation, state).await
194 }
195 }
196
197 pub struct OperationWrapper<S: Send + Sync + Clone> {
198 func: Box<
199 dyn Fn(
200 AnyObject,
201 AnyOperation,
202 S,
203 )
204 -> Pin<Box<dyn Future<Output = Result<Vec<u8>, OperationError<Vec<u8>>>> + Send>>
205 + Send
206 + Sync,
207 >,
208 object_name: String,
209 }
210
211 impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> {
212 pub fn new<
213 O: GiteratedObject + Send + Sync,
214 D: GiteratedOperation<O> + 'static,
215 F: GiteratedOperationHandler<O, D, S> + Send + Sync + 'static + Clone,
216 >(
217 handler: F,
218 ) -> Self {
219 let handler = Arc::new(Box::pin(handler));
220 Self {
221 func: Box::new(move |any_object, any_operation, state| {
222 let handler = handler.clone();
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 }
247 }
248
249 async fn handle(
250 &self,
251 object: AnyObject,
252 operation: AnyOperation,
253 state: S,
254 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
255 (self.func)(object, operation, state).await
256 }
257 }
258