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

ambee/giterated

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

Create `NetworkedSubstack`.

# giterated-protocol - Create `NetworkedSubstack` which will handle all networked operations giterated needs - Add support for `NetworkedSubstack` for both the daemon and client - Pipe everything through but leave APIs temp # `giterated-daemon` - Remove a bunch of random old code, dead code, and files that aren't needed. - Moved all connection handling to `client.rs`, simplified connection logic with new types

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨202bb12

⁨giterated-stack/src/substack.rs⁩ - ⁨11085⁩ 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(
180 object.clone(),
181 AnyValue::new(setting.clone()),
182 &operation_state,
183 )
184 .await;
185 Ok(())
186 }
187 .boxed_local()
188 },
189 ),
190 );
191
192 let wrapped = HandlerWrapper::new(
193 self.state.clone(),
194 |object: AnyObject,
195 _name: String,
196 _state: _,
197 _operation_state: StackOperationState,
198 stack: Arc<GiteratedStack>| {
199 info!("a setting handler called");
200 let object = object.clone();
201 async move {
202 match stack
203 .new_get_setting::<O, T>(object.downcast_ref().unwrap())
204 .await
205 {
206 Ok(setting) => Ok(AnyValue::new(setting)),
207 Err(err) => {
208 panic!("Error: {:?}", err);
209 }
210 }
211 }
212 .boxed_local()
213 },
214 );
215
216 self.value_getters
217 .insert(ObjectValuePair::from_types::<O, T>(), wrapped);
218
219 self
220 }
221
222 /// Register a [`GiteratedObjectValue<O>`] type with the runtime, providing
223 /// its associated handler for [`GetValue`].
224 ///
225 /// # Type Registration
226 /// This will register the provided [`GiteratedObjectValue`] type for its matching / specified
227 /// object type. It will **not** register the object type automatically.
228 pub fn dynamic_value<O, A, F>(&mut self, handler: F) -> &mut Self
229 where
230 O: MaybeDynamicObject + 'static,
231 F: IntoGiteratedHandler<
232 (O, String),
233 A,
234 S,
235 StackOperationState,
236 Result<AnyValue, OperationError<anyhow::Error>>,
237 > + Send
238 + Sync,
239 F: 'static,
240 {
241 let wrapped = HandlerWrapper::new(self.state.clone(), handler);
242
243 let wrapped = wrapped.map(
244 |(any_object, name): &(AnyObject, String), _state: &StackOperationState| {
245 Ok((O::from_any(any_object), name.clone()))
246 },
247 );
248
249 let wrapped = wrapped.map_return(|ret_val, _state| match ret_val {
250 Ok(success) => Ok(success.into_any()),
251 Err(err) => Err(match err {
252 OperationError::Operation(failure) => OperationError::Internal(failure.into()),
253 OperationError::Internal(err) => OperationError::Internal(err),
254 OperationError::Unhandled => OperationError::Unhandled,
255 }),
256 });
257
258 assert!(self
259 .value_getters
260 .insert(
261 ObjectValuePair {
262 object_kind: O::object_name(),
263 value_kind: "any"
264 },
265 wrapped
266 )
267 .is_none());
268
269 self
270 }
271
272 pub fn value_change<O, A, F, V>(&mut self, handler: F) -> &mut Self
273 where
274 F: IntoGiteratedHandler<
275 (O, V),
276 A,
277 S,
278 StackOperationState,
279 Result<(), OperationError<anyhow::Error>>,
280 > + Send
281 + Sync,
282 V: MaybeDynamicValue + Clone + 'static,
283 O: 'static + MaybeDynamicObject,
284 V: 'static,
285 F: 'static,
286 {
287 let wrapped = HandlerWrapper::new(self.state.clone(), handler);
288
289 let wrapped = wrapped.map(
290 |(any_object, any_value): &(AnyObject, AnyValue), _state: &StackOperationState| {
291 Ok((O::from_any(any_object), V::from_any(any_value)))
292 },
293 );
294
295 assert!(self
296 .value_change
297 .insert(
298 ObjectValuePair {
299 object_kind: O::object_name(),
300 value_kind: V::value_name()
301 },
302 wrapped
303 )
304 .is_none());
305
306 self
307 }
308
309 pub fn object_metadata_provider(&mut self, provider: Box<dyn MetadataProvider>) -> &mut Self {
310 self.metadata_providers.push(provider);
311
312 self
313 }
314 }
315
316 // Placeholder
317 impl<S: Send + Sync + Clone + 'static> SubstackBuilder<S> {
318 pub fn dynamic_operation<H>(&mut self, _handler: H) -> &mut Self {
319 todo!()
320 }
321 }
322 #[derive(Debug, Clone, thiserror::Error)]
323 #[error("downcast error")]
324 pub struct DowncastError;
325