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

ambee/giterated

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

Beginning of `stack-next` refactor

-Refactoring the protocol stack into something similar to a runtime. -Handles merging handler builders which is placing the ground work for plugins in. - Increased metadata generation during compilation enables less ser/de during execution. - Goal is to have an O(1) time from incoming operation to calling handlers. - Decreased penalty for using the statically typed API from within your code, now avoids some allocation. # Changes - Added `GiteratedRuntime` which is to replace the current unified stack - Added `RuntimeBuilder` which does what the current `OperationHandlers` struct does, but much better. - Added `RuntimeMetadata` to store type metadata for new `Any` based internals - Refactored serde_json out of the internal operation handling

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨708dea4

⁨giterated-stack/src/runtime.rs⁩ - ⁨16806⁩ bytes
Raw
1 use std::{any::Any, collections::HashMap};
2
3 use giterated_models::{
4 authenticated::AuthenticatedPayload,
5 error::OperationError,
6 message::GiteratedMessage,
7 object::{AnyObject, GiteratedObject},
8 operation::{AnyOperation, AnyOperationV2, GiteratedOperation},
9 settings::{AnySetting, GetSetting, SetSetting, Setting},
10 value::{GetValue, GetValueV2, GiteratedObjectValue},
11 };
12 use tracing::trace;
13
14 use crate::{
15 GiteratedOperationHandler, ObjectMeta, ObjectOperationPair, ObjectValuePair, OperationMeta,
16 OperationWrapper, SettingMeta, StackOperationState, ValueMeta,
17 };
18
19 /// Temporary name for the next generation of Giterated stack
20 pub struct GiteratedRuntime<S: GiteratedRuntimeState> {
21 operation_handlers: HashMap<ObjectOperationPair, HandlerTree<S>>,
22 value_getters: HashMap<ObjectValuePair, OperationWrapper<S>>,
23 setting_getters: HashMap<String, OperationWrapper<S>>,
24 metadata: RuntimeMetadata,
25 }
26
27 impl<S: GiteratedRuntimeState> GiteratedRuntime<S> {
28 pub fn merge_builder(&mut self, builder: RuntimeBuilder<S>) -> &mut Self {
29 for (target, handler) in builder.operation_handlers {
30 let tree = self.get_or_create_tree(&target);
31
32 tree.push(handler);
33 }
34
35 for (target, handler) in builder.value_getters {
36 assert!(self.value_getters.insert(target, handler).is_none());
37 }
38
39 for (target, handler) in builder.setting_getters {
40 assert!(self.setting_getters.insert(target, handler).is_none());
41 }
42
43 self.metadata.append(builder.metadata);
44
45 self
46 }
47
48 fn get_or_create_tree(&mut self, target: &ObjectOperationPair) -> &mut HandlerTree<S> {
49 if self.operation_handlers.contains_key(target) {
50 self.operation_handlers.get_mut(target).unwrap()
51 } else {
52 self.operation_handlers
53 .insert(target.clone(), HandlerTree::default());
54
55 self.operation_handlers.get_mut(target).unwrap()
56 }
57 }
58 }
59
60 pub struct HandlerTree<S: GiteratedRuntimeState> {
61 elements: Vec<OperationWrapper<S>>,
62 }
63
64 impl<S: GiteratedRuntimeState> Default for HandlerTree<S> {
65 fn default() -> Self {
66 Self { elements: vec![] }
67 }
68 }
69
70 impl<S: GiteratedRuntimeState> HandlerTree<S> {
71 pub fn push(&mut self, handler: OperationWrapper<S>) {
72 self.elements.push(handler);
73 }
74
75 pub fn handle(
76 &self,
77 object: &dyn Any,
78 operation: Box<dyn Any>,
79 state: &S,
80 operation_state: &StackOperationState,
81 ) -> Result<Box<dyn Any>, OperationError<Box<dyn Any>>> {
82 todo!()
83 }
84 }
85
86 /// Stores runtime metadata for all in-use Giterated protocol types.
87 #[derive(Default)]
88 struct RuntimeMetadata {
89 objects: HashMap<String, ObjectMeta>,
90 operations: HashMap<ObjectOperationPair, OperationMeta>,
91 values: HashMap<ObjectValuePair, ValueMeta>,
92 settings: HashMap<String, SettingMeta>,
93 }
94
95 /// Defines a type that is a valid Giterated runtime state.
96 ///
97 /// This allows for extraction of state in handlers, based on a
98 /// [`FromOperationState<S>`] impl on (what is in this case) [`Self`].
99 pub trait GiteratedRuntimeState: Send + Sync + Clone {}
100
101 impl<T: Send + Sync + Clone> GiteratedRuntimeState for T {}
102
103 #[derive(Default)]
104 pub struct RuntimeBuilder<S: GiteratedRuntimeState> {
105 operation_handlers: HashMap<ObjectOperationPair, OperationWrapper<S>>,
106 value_getters: HashMap<ObjectValuePair, OperationWrapper<S>>,
107 setting_getters: HashMap<String, OperationWrapper<S>>,
108 metadata: RuntimeMetadata,
109 }
110
111 impl<S: GiteratedRuntimeState + 'static> RuntimeBuilder<S> {
112 /// Insert an operation handler into the runtime builder.
113 ///
114 /// # Type Registration
115 /// Inserting the handler will automatically, if required, register the operation type of the
116 /// handler. It will **not** register the object type automatically.
117 pub fn operation<A, O, D, H>(&mut self, handler: H) -> &mut Self
118 where
119 O: GiteratedObject + 'static,
120 D: GiteratedOperation<O> + 'static,
121 H: GiteratedOperationHandler<A, O, D, S> + 'static + Clone,
122 {
123 let object_name = handler.object_name().to_string();
124 let operation_name = handler.operation_name().to_string();
125
126 let wrapped = OperationWrapper::new(handler);
127
128 let pair = ObjectOperationPair {
129 object_name,
130 operation_name,
131 };
132
133 assert!(self.operation_handlers.insert(pair, wrapped).is_none());
134
135 self.metadata.register_operation::<O, D>();
136
137 self
138 }
139
140 /// Register a [`GiteratedObject`] type with the runtime.
141 ///
142 /// # Type Registration
143 /// This will register the provided object type.
144 pub fn object<O: GiteratedObject + 'static>(&mut self) -> &mut Self {
145 self.metadata.register_object::<O>();
146
147 self
148 }
149
150 /// Register a [`Setting`] type with the runtime.
151 ///
152 /// # Type Registration
153 /// This will register the provided setting type.
154 pub fn setting<T: Setting>(&mut self) -> &mut Self {
155 self.metadata.register_setting::<T>();
156
157 self
158 }
159
160 /// Register a [`GiteratedObjectValue<O>`] type with the runtime, providing
161 /// its associated handler for [`GetValue`].
162 ///
163 /// # Type Registration
164 /// This will register the provided [`GiteratedObjectValue`] type for its matching / specified
165 /// object type. It will **not** register the object type automatically.
166 pub fn value<O, V, A, F>(&mut self, handler: F) -> &mut Self
167 where
168 O: GiteratedObject + 'static,
169 V: GiteratedObjectValue<Object = O> + 'static,
170 F: GiteratedOperationHandler<A, O, GetValue<V>, S> + Clone + 'static,
171 {
172 let object_name = handler.object_name().to_string();
173 let value_name = V::value_name().to_string();
174
175 let wrapped = OperationWrapper::new(handler);
176
177 assert!(self
178 .value_getters
179 .insert(
180 ObjectValuePair {
181 object_kind: object_name,
182 value_kind: value_name
183 },
184 wrapped
185 )
186 .is_none());
187
188 self.metadata.register_value::<O, V>();
189
190 self
191 }
192
193 /// Register a handler for [`GetSetting`] for it's associated object type.
194 pub fn object_settings<O, A, F>(&mut self, handler: F) -> &mut Self
195 where
196 O: GiteratedObject + 'static,
197 F: GiteratedOperationHandler<A, O, GetSetting, S> + Clone + 'static,
198 {
199 let object_name = handler.object_name().to_string();
200
201 let wrapped = OperationWrapper::new(handler);
202
203 assert!(self.setting_getters.insert(object_name, wrapped).is_none());
204
205 self
206 }
207 }
208
209 impl RuntimeMetadata {
210 fn register_object<O: GiteratedObject + 'static>(&mut self) {
211 let object_name = O::object_name().to_string();
212
213 let object_meta = ObjectMeta {
214 name: object_name.clone(),
215 from_str: Box::new(|str| Ok(Box::new(O::from_str(&str).map_err(|_| ())?))),
216 any_is_same: Box::new(|any| any.is::<O>()),
217 };
218
219 if self.objects.insert(object_name, object_meta).is_some() {
220 trace!(
221 "Registration of object {} overwrote previous registration.",
222 O::object_name()
223 );
224 } else {
225 trace!("Registration of object {}.", O::object_name())
226 }
227 }
228
229 fn register_operation<O: GiteratedObject + 'static, D: GiteratedOperation<O> + 'static>(
230 &mut self,
231 ) {
232 let object_name = O::object_name().to_string();
233 let operation_name = D::operation_name().to_string();
234
235 if self
236 .operations
237 .insert(
238 ObjectOperationPair {
239 object_name: object_name.clone(),
240 operation_name: operation_name.clone(),
241 },
242 OperationMeta {
243 name: operation_name,
244 object_kind: object_name,
245 deserialize: Box::new(|bytes| {
246 Ok(Box::new(serde_json::from_slice::<D>(bytes).unwrap())
247 as Box<dyn Any + Send + Sync>)
248 }),
249 any_is_same: Box::new(|any_box| any_box.is::<D>()),
250 serialize_success: Box::new(|any| {
251 let to_serialize = any.downcast::<D::Success>().unwrap();
252 serde_json::to_vec(&to_serialize)
253 }),
254 serialize_error: Box::new(|any| {
255 let to_serialize = any.downcast::<D::Failure>().unwrap();
256 serde_json::to_vec(&to_serialize)
257 }),
258 },
259 )
260 .is_some()
261 {
262 trace!(
263 "Registration of object operation {}<{}> overwrote previous registration.",
264 D::operation_name(),
265 O::object_name()
266 );
267 } else {
268 trace!(
269 "Registration of object operation {}<{}>.",
270 D::operation_name(),
271 O::object_name()
272 )
273 }
274 }
275
276 fn register_value<
277 O: GiteratedObject + 'static,
278 V: GiteratedObjectValue<Object = O> + 'static,
279 >(
280 &mut self,
281 ) {
282 let object_name = O::object_name().to_string();
283 let value_name = V::value_name().to_string();
284
285 if self
286 .values
287 .insert(
288 ObjectValuePair {
289 object_kind: object_name.clone(),
290 value_kind: value_name.clone(),
291 },
292 ValueMeta {
293 name: value_name,
294 deserialize: Box::new(|bytes| Ok(Box::new(serde_json::from_slice(&bytes)?))),
295 },
296 )
297 .is_some()
298 {
299 trace!(
300 "Registration of value <{}>::{} overwrote previous registration.",
301 O::object_name(),
302 V::value_name()
303 );
304 } else {
305 trace!(
306 "Registration of value <{}>::{}.",
307 O::object_name(),
308 V::value_name()
309 );
310 }
311 }
312
313 fn register_setting<S: Setting>(&mut self) {
314 let setting_name = S::name().to_string();
315
316 if self
317 .settings
318 .insert(
319 setting_name.clone(),
320 SettingMeta {
321 name: setting_name,
322 deserialize: Box::new(|bytes| Ok(Box::new(serde_json::from_slice(bytes)?))),
323 },
324 )
325 .is_some()
326 {
327 trace!(
328 "Registration of setting {} overwrote previous registration.",
329 S::name()
330 );
331 } else {
332 trace!("Registration of setting {}.", S::name());
333 }
334 }
335
336 fn append(&mut self, other: Self) {
337 self.objects.extend(other.objects);
338 self.operations.extend(other.operations);
339 self.values.extend(other.values);
340 self.settings.extend(other.settings);
341 }
342 }
343
344 #[async_trait::async_trait]
345 impl<L, O, D, S> GiteratedOperationHandler<L, O, D, S> for GiteratedRuntime<S>
346 where
347 O: GiteratedObject + 'static,
348 D: GiteratedOperation<O> + 'static,
349 S: GiteratedRuntimeState,
350 {
351 fn operation_name(&self) -> &str {
352 D::operation_name()
353 }
354
355 fn object_name(&self) -> &str {
356 O::object_name()
357 }
358
359 async fn handle(
360 &self,
361 object: &O,
362 operation: D,
363 state: S,
364 operation_state: &StackOperationState,
365 ) -> Result<D::Success, OperationError<D::Failure>> {
366 // Erase object and operation types.
367 let object = object as &dyn Any;
368 let operation = Box::new(operation) as Box<dyn Any>;
369
370 // We need to determine the type of the object, iterate through all known
371 // object types and check if the &dyn Any we have is the same type as the
372 // object type.
373 let object_type = {
374 let mut object_type = None;
375
376 for (object_name, object_meta) in self.metadata.objects.iter() {
377 if (object_meta.any_is_same)(object) {
378 object_type = Some(object_name.clone());
379 break;
380 }
381 }
382
383 object_type
384 }
385 .ok_or_else(|| OperationError::Unhandled)?;
386
387 // We need to hijack get_value, set_setting, and get_setting.
388 if operation.is::<GetValueV2>() {
389 todo!()
390 } else if operation.is::<GetSetting>() {
391 todo!()
392 } else if operation.is::<SetSetting>() {
393 todo!()
394 }
395
396 // Resolve the operation from the known operations table.
397 let operation_type = {
398 let mut operation_type = None;
399
400 for (target, operation_meta) in self.metadata.operations.iter() {
401 // Skip elements that we know will not match
402 if target.object_name != object_type {
403 continue;
404 }
405
406 if (operation_meta.any_is_same)(&operation) {
407 operation_type = Some(target.clone());
408 break;
409 }
410 }
411
412 operation_type
413 }
414 .ok_or_else(|| OperationError::Unhandled)?;
415
416 // Resolve the handler from our handler tree
417 let handler_tree = self
418 .operation_handlers
419 .get(&operation_type)
420 .ok_or_else(|| OperationError::Unhandled)?;
421
422 let raw_result = handler_tree.handle(object, operation, &state, operation_state);
423
424 // Convert the dynamic result back into its concrete type
425 match raw_result {
426 Ok(result) => Ok(*result.downcast::<D::Success>().unwrap()),
427 Err(err) => Err(match err {
428 OperationError::Internal(internal) => OperationError::Internal(internal),
429 OperationError::Operation(boxed_error) => {
430 OperationError::Operation(*boxed_error.downcast::<D::Failure>().unwrap())
431 }
432 OperationError::Unhandled => OperationError::Unhandled,
433 }),
434 }
435 }
436 }
437
438 impl<S: GiteratedRuntimeState> GiteratedRuntime<S> {
439 /// Handles a giterated network message, returning either a raw success
440 /// payload or a serialized error payload.
441 pub async fn handle_network_message(
442 &self,
443 message: AuthenticatedPayload,
444 state: &S,
445 operation_state: &StackOperationState,
446 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
447 let message: GiteratedMessage<AnyObject, AnyOperationV2> = message.into_message_v2();
448
449 // Deserialize the object, also getting the object type's name
450 let (object_type, object) = {
451 let mut result = None;
452
453 for (object_type, object_meta) in self.metadata.objects.iter() {
454 if let Ok(object) = (object_meta.from_str)(&message.object.0) {
455 result = Some((object_type.clone(), object));
456 break;
457 }
458 }
459
460 result
461 }
462 .ok_or_else(|| OperationError::Unhandled)?;
463
464 let target = ObjectOperationPair {
465 object_name: object_type,
466 operation_name: message.operation,
467 };
468
469 // Resolve the target operations from the handlers table
470 let handler = self
471 .operation_handlers
472 .get(&target)
473 .ok_or_else(|| OperationError::Unhandled)?;
474
475 // Deserialize the operation
476 let meta = self
477 .metadata
478 .operations
479 .get(&target)
480 .ok_or_else(|| OperationError::Unhandled)?;
481
482 let operation =
483 (meta.deserialize)(&message.payload.0).map_err(|_| OperationError::Unhandled)?;
484
485 // Get the raw result of the operation, where the return values are boxed.
486 let raw_result = handler.handle(&object, operation, state, operation_state);
487
488 // Deserialize the raw result for the network
489 match raw_result {
490 Ok(success) => Ok((meta.serialize_success)(success)
491 .map_err(|e| OperationError::Internal(e.to_string()))?),
492 Err(err) => Err(match err {
493 OperationError::Operation(failure) => OperationError::Operation(
494 (meta.serialize_error)(failure)
495 .map_err(|e| OperationError::Internal(e.to_string()))?,
496 ),
497 OperationError::Internal(internal) => OperationError::Internal(internal),
498 OperationError::Unhandled => OperationError::Unhandled,
499 }),
500 }
501 }
502 }
503