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

ambee/giterated

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

`giterated_cache` initial implementation

# Giterated Stack - Added the ability for dynamic substack handlers to exist for operations relevant to caching. - Added type metadata to the dynamic types. # Giterated Cache - Created - Implemented caching and fetching from cache. Hell fucking yes!!!! It works so good. Are you snooping in the commit logs because you're curious about the history of giterated? Cool that it got so big... tell me I say hi :)

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨86afeef

⁨giterated-stack/src/substack.rs⁩ - ⁨10773⁩ bytes
Raw
1 use std::{collections::HashMap, sync::Arc};
2
3 use futures_util::FutureExt;
4 use giterated_models::{
5 error::OperationError,
6 instance::Instance,
7 object::{GiteratedObject, ObjectRequest, ObjectResponse},
8 operation::GiteratedOperation,
9 settings::Setting,
10 value::GiteratedObjectValue,
11 };
12 use tracing::{info, trace};
13
14 use crate::{
15 handler::HandlerWrapper, provider::MetadataProvider, AnyFailure, AnyObject, AnyOperation,
16 AnySetting, AnySuccess, AnyValue, GiteratedStack, GiteratedStackState, IntoGiteratedHandler,
17 MaybeDynamicObject, MaybeDynamicValue, ObjectOperationPair, ObjectSettingPair, ObjectValuePair,
18 OperationHandler, RuntimeMetadata, SettingChange, SettingGetter, StackOperationState,
19 ValueChange, ValueGetter,
20 };
21
22 pub struct SubstackBuilder<S: GiteratedStackState> {
23 pub(crate) operation_handlers: HashMap<ObjectOperationPair<'static>, OperationHandler>,
24 pub(crate) value_getters: HashMap<ObjectValuePair<'static>, ValueGetter>,
25 pub(crate) setting_getters: HashMap<&'static str, SettingGetter>,
26 pub(crate) metadata: RuntimeMetadata,
27 pub(crate) value_change: HashMap<ObjectValuePair<'static>, ValueChange>,
28 pub(crate) metadata_providers: Vec<Box<dyn MetadataProvider>>,
29 pub(crate) setting_change: HashMap<ObjectSettingPair<'static>, SettingChange>,
30
31 pub(crate) state: S,
32 }
33
34 impl<S: GiteratedStackState + 'static> SubstackBuilder<S> {
35 pub fn new(state: S) -> Self {
36 Self {
37 operation_handlers: Default::default(),
38 value_getters: Default::default(),
39 setting_getters: Default::default(),
40 metadata: Default::default(),
41 value_change: Default::default(),
42 metadata_providers: Default::default(),
43 setting_change: Default::default(),
44 state,
45 }
46 }
47 }
48
49 impl<S: Send + Sync + Clone + 'static> SubstackBuilder<S> {
50 /// Insert an operation handler into the runtime builder.
51 ///
52 /// # Type Registration
53 /// Inserting the handler will automatically, if required, register the operation type of the
54 /// handler. It will **not** register the object type automatically.
55 pub fn operation<O, D, A, H>(&mut self, handler: H) -> &mut Self
56 where
57 O: GiteratedObject + Clone,
58 D: GiteratedOperation<O> + Clone,
59 H: IntoGiteratedHandler<
60 (O, D),
61 A,
62 S,
63 StackOperationState,
64 Result<D::Success, OperationError<D::Failure>>,
65 > + Send
66 + Sync
67 + 'static,
68 O: 'static,
69 D: 'static,
70 D::Failure: std::fmt::Debug + 'static,
71 D::Success: 'static,
72 {
73 let wrapped = HandlerWrapper::new(self.state.clone(), handler);
74
75 let wrapped = wrapped.map(
76 |(any_object, any_operation): &(AnyObject, AnyOperation),
77 _state: &StackOperationState| {
78 Ok((
79 any_object.downcast_ref::<O>().unwrap().clone(),
80 any_operation.downcast_ref::<D>().unwrap().clone(),
81 ))
82 },
83 );
84
85 let wrapped = wrapped.map_return(|ret_val, _state| match ret_val {
86 Ok(success) => Ok(AnySuccess(Arc::new(success))),
87 Err(err) => Err(match err {
88 OperationError::Operation(failure) => {
89 OperationError::Operation(AnyFailure(Arc::new(failure)))
90 }
91 OperationError::Internal(err) => OperationError::Internal(err),
92 OperationError::Unhandled => OperationError::Unhandled,
93 }),
94 });
95
96 let pair = ObjectOperationPair::from_types::<O, D>();
97
98 self.operation_handlers.insert(pair, wrapped);
99
100 self.metadata.register_operation::<O, D>();
101
102 self
103 }
104
105 /// Register a [`GiteratedObject`] type with the runtime.
106 ///
107 /// # Type Registration
108 /// This will register the provided object type.
109 pub fn object<O: GiteratedObject + 'static>(&mut self) -> &mut Self {
110 self.metadata.register_object::<O>();
111
112 // Insert handler so ObjectRequest is handled properly
113
114 self.operation(
115 move |_object: Instance,
116 operation: ObjectRequest,
117 _state: S,
118 _operation_state: StackOperationState,
119 stack: Arc<GiteratedStack>| {
120 let operation = operation.clone();
121 async move {
122 for (_object_name, object_meta) in stack.metadata.objects.iter() {
123 if (object_meta.from_str)(&operation.0).is_ok() {
124 return Ok(ObjectResponse(operation.0.clone()));
125 }
126 }
127
128 Err(OperationError::Unhandled)
129 }
130 .boxed_local()
131 },
132 );
133
134 self
135 }
136
137 /// Register a [`Setting`] type with the runtime.
138 ///
139 /// # Type Registration
140 /// This will register the provided setting type.
141 pub fn setting<O: GiteratedObject + 'static, T: Setting + 'static + Clone>(
142 &mut self,
143 ) -> &mut Self {
144 self.metadata.register_setting::<O, T>();
145
146 self
147 }
148
149 /// Register a [`GiteratedObjectValue`] that is also a [`Setting`], which
150 /// allows for automatic value updates.
151 pub fn value_setting<
152 O: GiteratedObject + 'static + Clone,
153 T: GiteratedObjectValue<Object = O> + Setting + 'static + Clone,
154 >(
155 &mut self,
156 ) -> &mut Self {
157 self.metadata.register_setting::<O, T>();
158 self.metadata.register_value::<O, T>();
159
160 self.setting_change.insert(
161 ObjectSettingPair::from_types::<O, T>(),
162 HandlerWrapper::new(
163 (),
164 move |object: AnyObject,
165 setting: AnySetting,
166 _state: (),
167 operation_state: StackOperationState,
168 stack: Arc<GiteratedStack>| {
169 trace!(
170 "value setting updated {}::{}",
171 O::object_name(),
172 T::value_name()
173 );
174 let object = object.clone();
175 async move {
176 let object = object.downcast_ref::<O>().unwrap();
177 let setting = setting.downcast_ref::<T>().unwrap();
178 stack
179 .value_update(object.clone(), setting.clone(), &operation_state)
180 .await;
181 Ok(())
182 }
183 .boxed_local()
184 },
185 ),
186 );
187
188 let wrapped = HandlerWrapper::new(
189 self.state.clone(),
190 |object: AnyObject,
191 _name: String,
192 _state: _,
193 _operation_state: StackOperationState,
194 stack: Arc<GiteratedStack>| {
195 info!("a setting handler called");
196 let object = object.clone();
197 async move {
198 match stack
199 .new_get_setting::<O, T>(object.downcast_ref().unwrap())
200 .await
201 {
202 Ok(setting) => Ok(AnyValue::new(setting)),
203 Err(err) => {
204 panic!("Error: {:?}", err);
205 }
206 }
207 }
208 .boxed_local()
209 },
210 );
211
212 self.value_getters
213 .insert(ObjectValuePair::from_types::<O, T>(), wrapped);
214
215 self
216 }
217
218 /// Register a [`GiteratedObjectValue<O>`] type with the runtime, providing
219 /// its associated handler for [`GetValue`].
220 ///
221 /// # Type Registration
222 /// This will register the provided [`GiteratedObjectValue`] type for its matching / specified
223 /// object type. It will **not** register the object type automatically.
224 pub fn dynamic_value<O, A, F>(&mut self, handler: F) -> &mut Self
225 where
226 O: MaybeDynamicObject + 'static,
227 F: IntoGiteratedHandler<
228 (O, String),
229 A,
230 S,
231 StackOperationState,
232 Result<AnyValue, OperationError<anyhow::Error>>,
233 > + Send
234 + Sync,
235 F: 'static,
236 {
237 let wrapped = HandlerWrapper::new(self.state.clone(), handler);
238
239 let wrapped = wrapped.map(
240 |(any_object, name): &(AnyObject, String), _state: &StackOperationState| {
241 Ok((O::from_any(any_object), name.clone()))
242 },
243 );
244
245 let wrapped = wrapped.map_return(|ret_val, _state| match ret_val {
246 Ok(success) => Ok(success.into_any()),
247 Err(err) => Err(match err {
248 OperationError::Operation(failure) => OperationError::Internal(failure.into()),
249 OperationError::Internal(err) => OperationError::Internal(err),
250 OperationError::Unhandled => OperationError::Unhandled,
251 }),
252 });
253
254 assert!(self
255 .value_getters
256 .insert(
257 ObjectValuePair {
258 object_kind: O::object_name(),
259 value_kind: "any"
260 },
261 wrapped
262 )
263 .is_none());
264
265 self
266 }
267
268 pub fn value_change<O, A, F, V>(&mut self, handler: F) -> &mut Self
269 where
270 F: IntoGiteratedHandler<
271 (O, V),
272 A,
273 S,
274 StackOperationState,
275 Result<(), OperationError<anyhow::Error>>,
276 > + Send
277 + Sync,
278 V: MaybeDynamicValue + Clone + 'static,
279 O: 'static + MaybeDynamicObject,
280 V: 'static,
281 F: 'static,
282 {
283 let wrapped = HandlerWrapper::new(self.state.clone(), handler);
284
285 let wrapped = wrapped.map(
286 |(any_object, any_value): &(AnyObject, AnyValue), _state: &StackOperationState| {
287 Ok((O::from_any(any_object), V::from_any(any_value)))
288 },
289 );
290
291 assert!(self
292 .value_change
293 .insert(
294 ObjectValuePair {
295 object_kind: O::object_name(),
296 value_kind: V::value_name()
297 },
298 wrapped
299 )
300 .is_none());
301
302 self
303 }
304
305 pub fn object_metadata_provider(&mut self, provider: Box<dyn MetadataProvider>) -> &mut Self {
306 self.metadata_providers.push(provider);
307
308 self
309 }
310 }
311
312 #[derive(Debug, Clone, thiserror::Error)]
313 #[error("downcast error")]
314 pub struct DowncastError;
315