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

ambee/giterated

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

Major refactor to handler traits

Added `IntoGiteratedHandler`, which is the new trait for handler functions. This allows us to finally get rid of the Object and ObjectOperation bounds that resulted in hacks around the newer features of the unified stack. Squashed commit of the following: commit 62e1ecf76ee31cda0bab4602d9d00fa0dc2f9158 Author: Amber <[email protected]> Date: Wed Oct 11 09:31:11 2023 -0500 Update commit dfd2d1b0b5d81ee3bc48f0321c6aceaa677e3b8b Author: Amber <[email protected]> Date: Wed Oct 11 09:31:07 2023 -0500 Major refactor to handler traits Added `IntoGiteratedHandler`, which is the new trait for handler functions. This allows us to finally get rid of the Object and ObjectOperation bounds that resulted in hacks around the newer features of the unified stack. Removed dead and legacy code. I think... commit 57b4b398eff32e69f2f4b9700e42a1277a4d1055 Author: Amber <[email protected]> Date: Sun Oct 1 23:05:10 2023 -0500 New handler trait for giterated stack Refactor the old handler trait so it is more generic and can be used for specific kinds of handlers

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨90c4780

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