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/handler/mod.rs⁩ - ⁨7670⁩ bytes
Raw
1 use std::{any::Any, sync::Arc};
2 pub mod handler_impl;
3 use futures_util::{future::LocalBoxFuture, Future, FutureExt};
4 use giterated_models::error::OperationError;
5
6 use crate::{
7 AuthenticatedInstance, AuthenticatedUser, GiteratedStack, MissingValue, StackOperationState,
8 };
9
10 #[async_trait::async_trait(?Send)]
11 pub trait IntoGiteratedHandler<Params, AdditionalParams, State, OState, Output>
12 where
13 // Output cannot have non-static references
14 Output: 'static,
15 {
16 type Future: Future<Output = Output>;
17
18 async fn handle(&self, parameters: Params, state: State, operation_state: OState) -> Output;
19 }
20
21 pub struct HandlerTree<Kind> {
22 elements: Vec<Kind>,
23 }
24
25 impl<Kind> Default for HandlerTree<Kind> {
26 fn default() -> Self {
27 Self {
28 elements: Default::default(),
29 }
30 }
31 }
32
33 impl<'fut: 'o + 'p, 'p, 'o, P, O, E> HandlerTree<HandlerWrapper<P, O, E>>
34 where
35 P: Clone,
36 {
37 pub fn push(&mut self, handler: HandlerWrapper<P, O, E>) {
38 self.elements.push(handler);
39 }
40 pub async fn handle(
41 &self,
42 parameters: P,
43 operation_state: StackOperationState,
44 ) -> Result<O, OperationError<E>> {
45 for handler in self.elements.iter() {
46 match handler
47 .handle(parameters.clone(), operation_state.clone())
48 .await
49 {
50 Ok(handled) => return Ok(handled),
51 Err(err) => match err {
52 OperationError::Internal(err) => return Err(OperationError::Internal(err)),
53 OperationError::Operation(err) => return Err(OperationError::Operation(err)),
54 OperationError::Unhandled => continue,
55 },
56 }
57 }
58
59 Err(OperationError::Unhandled)
60 }
61 }
62
63 pub struct HandlerWrapper<P, O, E> {
64 func: Arc<
65 dyn Fn(
66 P,
67 Arc<dyn Any + Send + Sync>,
68 StackOperationState,
69 ) -> LocalBoxFuture<'static, Result<O, OperationError<E>>>
70 + Send
71 + Sync,
72 >,
73 state: Arc<dyn Any + Send + Sync>,
74 }
75
76 impl<P, O, E> HandlerWrapper<P, O, E> {
77 pub fn new<S, F, A>(state: S, handler: F) -> Self
78 where
79 F: IntoGiteratedHandler<P, A, S, StackOperationState, Result<O, OperationError<E>>>
80 + Send
81 + Sync,
82 S: Send + Sync + Clone + 'static,
83 E: 'static,
84 P: 'static + Clone,
85 F: 'static,
86 O: 'static,
87 {
88 let state = Arc::new(state);
89
90 let handler_func = Arc::new(handler);
91 let state_two = state.clone();
92 HandlerWrapper {
93 func: Arc::new(
94 move |args: P,
95 state: Arc<dyn Any + Send + Sync>,
96 operation_state: StackOperationState| {
97 let handler = handler_func.clone();
98 let operation_state = operation_state.clone();
99 let state = state.downcast_ref::<S>().unwrap();
100 let state = state.clone();
101 async move {
102 let handler = handler.clone();
103 let operation_state = operation_state;
104 handler.handle(args, state, operation_state).await
105 }
106 .boxed_local()
107 },
108 ),
109 state: state_two,
110 }
111 }
112
113 pub async fn handle(
114 &self,
115 required: P,
116 operation_state: StackOperationState,
117 ) -> Result<O, OperationError<E>> {
118 (self.func)(required, self.state.clone(), operation_state).await
119 }
120
121 pub fn map<F, N, R>(self, predicate: F) -> HandlerWrapper<N, O, R>
122 where
123 F: Fn(&N, &StackOperationState) -> Result<P, OperationError<R>> + Clone + Send + Sync,
124 R: std::fmt::Debug + 'static,
125 E: Into<OperationError<R>> + 'static,
126 F: 'static,
127 N: 'static,
128 P: 'static,
129 O: 'static,
130 {
131 let func = Arc::new(self.func);
132 let predicate = Arc::new(predicate);
133 HandlerWrapper {
134 func: Arc::new(
135 move |args: N,
136 state: Arc<dyn Any + Send + Sync>,
137 operation_state: StackOperationState| {
138 let predicate_output = predicate(&args, &operation_state);
139 let func = func.clone();
140 let operation_state: StackOperationState = operation_state.clone();
141 async move {
142 let predicate_output = predicate_output?;
143 let operation_state = operation_state;
144 match (func)(predicate_output, state, operation_state).await {
145 Ok(success) => Ok(success),
146 Err(_) => todo!(),
147 }
148 }
149 .boxed_local()
150 },
151 ),
152 state: self.state,
153 }
154 }
155
156 pub fn map_return<F, NR, NE>(self, predicate: F) -> HandlerWrapper<P, NR, NE>
157 where
158 F: Fn(Result<O, OperationError<E>>, &StackOperationState) -> Result<NR, OperationError<NE>>
159 + Clone
160 + Send
161 + Sync,
162 O: 'static,
163 F: 'static,
164 E: 'static,
165 P: 'static,
166 {
167 let predicate = Arc::new(predicate);
168 let func = self.func;
169 HandlerWrapper {
170 func: Arc::new(
171 move |args: P,
172 state: Arc<dyn Any + Send + Sync>,
173 operation_state: StackOperationState| {
174 let clone = predicate.clone();
175 let func = func.clone();
176 let _statoperation_statee = operation_state.clone();
177
178 async move {
179 let func = func.clone();
180 let clone = clone;
181 let operation_state = operation_state;
182 clone(
183 (func)(args, state, operation_state.clone()).await,
184 &operation_state,
185 )
186 }
187 .boxed_local()
188 },
189 ),
190 state: self.state,
191 }
192 }
193 }
194
195 #[async_trait::async_trait(?Send)]
196 pub trait HandlerResolvable<RequiredParameters, OperationState>: Sized {
197 type Error;
198
199 async fn from_handler_state(
200 required_parameters: &RequiredParameters,
201 operation_state: &OperationState,
202 ) -> Result<Self, Self::Error>;
203 }
204
205 #[async_trait::async_trait(?Send)]
206 impl<R> HandlerResolvable<R, StackOperationState> for Arc<GiteratedStack> {
207 type Error = MissingValue;
208
209 async fn from_handler_state(
210 _required_parameters: &R,
211 operation_state: &StackOperationState,
212 ) -> Result<Self, Self::Error> {
213 Ok(operation_state.runtime.clone())
214 }
215 }
216
217 #[async_trait::async_trait(?Send)]
218 impl<R> HandlerResolvable<R, StackOperationState> for AuthenticatedUser {
219 type Error = MissingValue;
220
221 async fn from_handler_state(
222 _required_parameters: &R,
223 operation_state: &StackOperationState,
224 ) -> Result<Self, Self::Error> {
225 operation_state.user.clone().ok_or_else(|| MissingValue)
226 }
227 }
228
229 #[async_trait::async_trait(?Send)]
230 impl<R> HandlerResolvable<R, StackOperationState> for AuthenticatedInstance {
231 type Error = MissingValue;
232
233 async fn from_handler_state(
234 _required_parameters: &R,
235 operation_state: &StackOperationState,
236 ) -> Result<Self, Self::Error> {
237 operation_state.instance.clone().ok_or_else(|| MissingValue)
238 }
239 }
240