dyer/plugin/
middleware.rs

1//! plugin that process data flow in and out of `Actor` between component.
2//!
3//! ```no_run
4//! # use crate::dyer::component::{Affix, Request, Response, Task};
5//! # use crate::dyer::{plug, MiddleWare};
6//! # use crate::dyer::engine::App;
7//! pub struct E;
8//! # async fn handle_affix(_affixs: &mut Vec<Affix>, _app: &mut App<E>) {}
9//! # async fn handle_task(_tasks: &mut Vec<Task>, _app: &mut App<E,  >) {}
10//! # async fn handle_req(
11//! #     _reqs: &mut Vec<Request>,
12//! #     _app: &mut App<E>,
13//! # ) -> (Vec<Task>, Vec<Affix>) {
14//! #     (vec![], vec![])
15//! # }
16//! # async fn handle_res(_res: &mut Vec<Response< >>, _app: &mut App<E>) {}
17//! # async fn handle_item(_items: &mut Vec<E>, _app: &mut App<E>) {}
18//! # async fn handle_err(_res: &mut Vec<Result<Response, MetaResponse>>, _app: &mut App<E>) {}
19//! # async fn handle_yerr(_res: &mut Vec<Result<Response, MetaResponse>>, _app: &mut App<E,  >) {}
20//! // to initialize a `MiddleWare`
21//! let middleware = MiddleWare::<E>::builder()
22//!     .affix(&handle_affix)
23//!     .task(&handle_task)
24//!     .err(&handle_err)
25//!     .build("middleware_id_here");
26//! // middleware is created with default `rank` 0
27//! // if you want it has higher privilege to be executed
28//! // increase it
29//! assert_eq!(middleware.rank(), 0);
30//! ```
31
32use crate::component::{Affix, Request, Response, Task};
33use crate::engine::App;
34use crate::plugin::BoxFuture;
35use crate::response::MetaResponse;
36use http::Extensions;
37
38/// default method for process `Affix` in `MiddleWare`
39pub async fn haffix<E>(_affixs: &mut Vec<Affix>, _app: &mut App<E>) {}
40
41/// default method for process `Task` in `MiddleWare`
42pub async fn htask<'r, 's, E>(_tasks: &mut Vec<Task>, _app: &mut App<E>) {}
43
44/// default method for process `Request` in `MiddleWare`
45pub async fn hreq<E>(_reqs: &mut Vec<Request>, _app: &mut App<E>) {}
46
47/// default method for process `Response` in `MiddleWare`
48pub async fn hres<E>(_res: &mut Vec<Response>, _app: &mut App<E>) {}
49
50/// default method for process `Item` in `MiddleWare`
51pub async fn hitem<E>(_items: &mut Vec<E>, _app: &mut App<E>) {}
52
53/// default method for process failed `Response` in `MiddleWare`
54pub async fn herr<E>(_res: &mut Vec<Result<Response, MetaResponse>>, _app: &mut App<E>) {
55    let tasks = Vec::new();
56    let affixs = Vec::new();
57    let mut reqs = Vec::new();
58    let mut yerrs = Vec::new();
59    while let Some(res) = _res.pop() {
60        match res {
61            Ok(mut item) => {
62                log::error!(
63                    "Response Failed: {}, uri: {}",
64                    item.status().as_u16(),
65                    item.metas.info.from.to_string()
66                );
67                let used = item.metas.info.used;
68                if used > 2 {
69                    /*
70                     *let errs = format!(
71                     *    "status: {}\turi: {}\tcontent: {:?}\n",
72                     *    &item.status().as_str(),
73                     *    &item.metas.info.from.to_string(),
74                     *    item.body
75                     *);
76                     */
77                    log::error!("Task Fails 3+ times. drop it.");
78                    // remove affix  as default
79                    yerrs.push(Ok(item));
80                } else {
81                    item.metas.info.used += 1;
82                    log::error!("{} Times Failure, Reuse This Task.", used + 1);
83                    if let Some(couple) = _app.couple.get(&item.metas.info.id) {
84                        let req = Request::from_couple(
85                            couple,
86                            None,
87                            _app.exts_t_fn.as_ref(),
88                            _app.exts_p_fn.as_ref(),
89                        );
90                        reqs.push(req);
91                    }
92                }
93            }
94            Err(mut m) => {
95                log::error!("Response Failed uri: {}", m.info.from.to_string());
96                let used = m.info.used;
97                if used > 2 {
98                    /*
99                     *let errs = format!(
100                     *    "cannot make a request to uri: {}\n",
101                     *    &m.info.from.to_string(),
102                     *);
103                     */
104                    log::error!("Task Fails 3+ times. drop it.");
105                    // remove affix  as default
106                    yerrs.push(Err(m));
107                } else {
108                    m.info.used += 1;
109                    log::error!("{} Times Failure, Reuse This Task.", used + 1);
110                    if let Some(couple) = _app.couple.get(&m.info.id) {
111                        let req = Request::from_couple(
112                            couple,
113                            None,
114                            _app.exts_t_fn.as_ref(),
115                            _app.exts_p_fn.as_ref(),
116                        );
117                        reqs.push(req);
118                    }
119                }
120            }
121        }
122    }
123    _app.task.as_mut().extend(tasks);
124    _app.affix.as_mut().extend(affixs);
125    _app.req.as_mut().extend(reqs);
126    _app.errs.as_mut().extend(yerrs);
127}
128
129/// default method for failing parsing `Response` in `MiddleWare`
130pub async fn hyerr<E>(_res: &mut Vec<Result<Response, MetaResponse>>, _app: &mut App<E>) {}
131
132macro_rules! builder {
133    ($f:ident, $var: ident, $hd: ident, $item:ty, $ref:ident, $bd: expr) => {
134        #[doc = "Set the `"]
135        #[doc = stringify!($item)]
136        #[doc = "` handler of `MiddleWare`, if not called, the default value is `None`"]
137        #[doc = ""]
138        #[doc = "# Examples"]
139        #[doc = ""]
140        #[doc = "```rust"]
141        #[doc = "# use dyer::middleware::*;"]
142        #[doc = concat!("async fn ", stringify!($hd), "(_: &mut Vec<", stringify!($item), ">, _: &mut App<E>) {}" )]
143        #[doc = concat!("let middleware = ", stringify!($bd))]
144        #[doc = concat!("    ", stringify!(.$f),"(&", stringify!($hd), ")" ) ]
145        #[doc = "    .build(\"marker\");"]
146        #[doc = stringify!(assert!(middleware.$hd.is_some()) )]
147        #[doc = "```"]
148        pub fn $f(
149            mut self,
150            $var: &'md dyn for<'a> Fn(&'a mut Vec<$item>, &'a mut App<E>) -> BoxFuture<'a, ()>,
151        ) -> Self
152        {
153            self.$hd = Some($var );
154            self
155        }
156
157        #[doc = "Get the shared reference of `"]
158        #[doc = stringify!($item)]
159        #[doc = "` handler of `MiddleWare`, if not set before, `None` is returned"]
160        #[doc = ""]
161        #[doc = "# Examples"]
162        #[doc = ""]
163        #[doc = "```rust"]
164        #[doc = "# use dyer::middleware::*;"]
165        #[doc = concat!("async fn ", stringify!($hd), "(_: &mut Vec<", stringify!($item), ">, _: &mut App<E>) {}" )]
166        #[doc = concat!("let middleware = ", stringify!($bd))]
167        #[doc = concat!("    ", stringify!(.$f),"(&", stringify!($hd), ")" ) ]
168        #[doc = "    .build(\"marker\");"]
169        #[doc = stringify!(assert_eq!(middleware.$ref(), Some($hd)) )]
170        #[doc = "```"]
171        pub fn $ref(&self) ->
172             Option<&'md dyn for<'a> Fn(&'a mut Vec<$item>, &'a mut App<E>) -> BoxFuture<'a, ()>>
173        {
174            self.$hd
175        }
176    };
177}
178
179/// Represents a medium that handles the dataflow of [App]
180///
181/// In practise, it handles every data structure's in-and-out during execution
182/// according to the `marker` and `rank`
183pub struct MiddleWare<'md, E> {
184    pub(crate) handle_affix:
185        Option<&'md dyn for<'a> Fn(&'a mut Vec<Affix>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
186
187    pub(crate) handle_task:
188        Option<&'md dyn for<'a> Fn(&'a mut Vec<Task>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
189
190    pub(crate) handle_req:
191        Option<&'md dyn for<'a> Fn(&'a mut Vec<Request>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
192    pub(crate) handle_res:
193        Option<&'md dyn for<'a> Fn(&'a mut Vec<Response>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
194    pub(crate) handle_entity:
195        Option<&'md dyn for<'a> Fn(&'a mut Vec<E>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
196    pub(crate) handle_yerr: Option<
197        &'md dyn for<'a> Fn(
198            &'a mut Vec<Result<Response, MetaResponse>>,
199            &'a mut App<E>,
200        ) -> BoxFuture<'a, ()>,
201    >,
202    pub(crate) handle_err: Option<
203        &'md dyn for<'a> Fn(
204            &'a mut Vec<Result<Response, MetaResponse>>,
205            &'a mut App<E>,
206        ) -> BoxFuture<'a, ()>,
207    >,
208    pub marker: String,
209    pub rank: i16,
210    pub extensions: Extensions,
211}
212
213impl<'md, E> MiddleWare<'md, E> {
214    /// Create an instance of `MiddleWareBuilder` that used to build a `MiddleWare`  
215    ///
216    /// # Examples
217    ///
218    /// ```rust
219    /// # use dyer::middleware::*;
220    /// async fn handle_task(&mut Vec<Task>, &mut App<E>) {}
221    /// let middleware = Middleware::builder()
222    ///     .task(handle_task)
223    ///     .build("marker");
224    /// ```
225    pub fn builder() -> MiddleWareBuilder<'md, E> {
226        MiddleWareBuilder::new()
227    }
228
229    /// get the rank of `MiddleWare`
230    ///
231    /// # Examples
232    ///
233    /// ```rust
234    /// # use dyer::middleWare::*;
235    /// async fn handle_task(&mut Vec<Task>, &mut App<E>) {}
236    /// let middleware = MiddleWare::builder()
237    ///     .rank(1)
238    ///     .build("marker");
239    /// assert_eq!(middleware.rank(), 0);
240    /// ```
241    pub fn rank(&self) -> i16 {
242        self.rank
243    }
244
245    /// get mutable reference to rank of `MiddleWare`
246    ///
247    /// # Examples
248    ///
249    /// ```rust
250    /// # use dyer::middleware::*;
251    /// async fn handle_task(&mut Vec<Task>, &mut App<E>) {}
252    /// let middleware = MiddleWare::builder()
253    ///     .task(handle_task)
254    ///     .build("marker");
255    /// middleware.rank_mut() = 3;
256    /// assert_eq!(middleware.rank(), 3);
257    /// ```
258    pub fn rank_mut(&mut self) -> &mut i16 {
259        &mut self.rank
260    }
261
262    /// mutate the extensions of `MiddleWare`
263    ///
264    /// # Examples
265    ///
266    /// ```rust
267    /// # use dyer::middleware::*;
268    /// let mut middleware = Middleware::builder()
269    ///     .extensions(1i32)
270    ///     .build("marker");
271    /// middleware.extension_mut().insert(2i32);
272    /// ```
273    pub fn extensions_mut(&mut self) -> &mut Extensions {
274        &mut self.extensions
275    }
276
277    /// get extensions of `MiddleWare`
278    ///
279    /// # Examples
280    ///
281    /// ```rust
282    /// # use dyer::middleware::*;
283    /// let middleware = Middleware::builder()
284    ///     .extensions(1i32)
285    ///     .build("marker");
286    /// assert_eq!(middleware.extensions().get::<i32>(), 1);
287    /// ```
288    pub fn extensions(&self) -> &Extensions {
289        &self.extensions
290    }
291
292    builder!(
293        task_mut,
294        task,
295        handle_task,
296        Task,
297        task,
298        MiddleWare::builder()
299    );
300    builder!(
301        affix_mut,
302        affix,
303        handle_affix,
304        Affix,
305        affix,
306        MiddleWare::builder()
307    );
308    builder!(
309        entity_mut,
310        entity,
311        handle_entity,
312        E,
313        entity,
314        MiddleWare::builder()
315    );
316    builder!(
317        req_mut,
318        req,
319        handle_req,
320        Request,
321        req,
322        MiddleWare::builder()
323    );
324    builder!(
325        res_mut,
326        res,
327        handle_res,
328        Response,
329        res,
330        MiddleWare::builder()
331    );
332    builder!(err_mut, err, handle_err, Result<Response, MetaResponse>, err, MiddleWare::builder());
333    builder!(yerr_mut, yerr, handle_yerr, Result<Response, MetaResponse>, yerr, MiddleWare::builder());
334}
335
336/// Serve as an medium to create an instance of [MiddleWare]
337///
338/// This type can be used to construct an instance or [MiddleWare]
339/// through a builder-like pattern.
340pub struct MiddleWareBuilder<'md, E> {
341    handle_affix:
342        Option<&'md dyn for<'a> Fn(&'a mut Vec<Affix>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
343
344    handle_task:
345        Option<&'md dyn for<'a> Fn(&'a mut Vec<Task>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
346
347    handle_req:
348        Option<&'md dyn for<'a> Fn(&'a mut Vec<Request>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
349    handle_res:
350        Option<&'md dyn for<'a> Fn(&'a mut Vec<Response>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
351    handle_entity: Option<&'md dyn for<'a> Fn(&'a mut Vec<E>, &'a mut App<E>) -> BoxFuture<'a, ()>>,
352    handle_yerr: Option<
353        &'md dyn for<'a> Fn(
354            &'a mut Vec<Result<Response, MetaResponse>>,
355            &'a mut App<E>,
356        ) -> BoxFuture<'a, ()>,
357    >,
358    handle_err: Option<
359        &'md dyn for<'a> Fn(
360            &'a mut Vec<Result<Response, MetaResponse>>,
361            &'a mut App<E>,
362        ) -> BoxFuture<'a, ()>,
363    >,
364    rank: i16,
365    extensions: Extensions,
366}
367
368impl<'md, E> MiddleWareBuilder<'md, E> {
369    /// Create an instance of `MiddleWare`
370    ///
371    /// # Examples
372    ///
373    /// ```rust
374    /// # use dyer::middleware::*;
375    /// let middleware = MiddlewareBuilder::new();
376    /// assert!(middleware.entity_ref().is_none());
377    /// ```
378    pub fn new() -> Self {
379        Self {
380            handle_entity: None,
381            handle_req: None,
382            handle_affix: None,
383            handle_task: None,
384            handle_res: None,
385            handle_err: None,
386            handle_yerr: None,
387            rank: 0,
388            extensions: Extensions::new(),
389        }
390    }
391
392    /// Consume it and return an instance of MiddleWare
393    ///
394    /// # Examples
395    ///
396    /// ```rust
397    /// # use dyer::middleware::*;
398    /// async fn handle_entity(_: &mut Vec<E>, _: &mut App<E>) {}
399    /// let middleware = MiddlewareBuilder::new();
400    ///     .entity(handle_entity)
401    ///     .build("marker");
402    /// ```
403    pub fn build<T: Into<String>>(self, marker: T) -> MiddleWare<'md, E> {
404        let all = self.handle_task.is_some()
405            || self.handle_affix.is_some()
406            || self.handle_req.is_some()
407            || self.handle_res.is_some()
408            || self.handle_entity.is_some()
409            || self.handle_err.is_some()
410            || self.handle_yerr.is_some();
411        assert!(all, "None of MiddleWare has been specified");
412        MiddleWare {
413            handle_task: self.handle_task,
414            handle_affix: self.handle_affix,
415            handle_req: self.handle_req,
416            handle_res: self.handle_res,
417            handle_entity: self.handle_entity,
418            handle_err: self.handle_err,
419            handle_yerr: self.handle_yerr,
420            marker: marker.into(),
421            rank: self.rank,
422            extensions: self.extensions,
423        }
424    }
425
426    /// set the extensions of `MiddleWareBuilder`
427    ///
428    /// # Examples
429    ///
430    /// ```rust
431    /// # use dyer::middleware::*;
432    /// let middleware = middleware::builder()
433    ///     .extensions(1i32)
434    ///     .build("marker");
435    /// assert_eq!(middleware.extensions().get::<i32>(), 1);
436    /// ```
437    pub fn extensions<S>(mut self, extensions: S) -> Self
438    where
439        S: std::any::Any + Send + Sync + 'static,
440    {
441        self.extensions.insert(extensions);
442        self
443    }
444
445    /// get extensions of `MiddleWareBuilder`
446    ///
447    /// # Examples
448    ///
449    /// ```rust
450    /// # use dyer::middleware::*;
451    /// let middleware = middleware::builder()
452    ///     .extensions(1i32)
453    ///     .build("marker");
454    /// assert_eq!(middleware.extensions_ref().get::<i32>(), 1);
455    /// ```
456    pub fn extensions_ref(&self) -> &Extensions {
457        &self.extensions
458    }
459
460    /// set the rank of `MiddleWareBuilder`
461    ///
462    /// # Examples
463    ///
464    /// ```rust
465    /// # use dyer::middleWare::*;
466    /// let middleware = MiddleWareBuilder::new()
467    ///     .rank(1)
468    ///     .build("marker");
469    /// assert_eq!(middleware.rank_ref(), 1);
470    /// ```
471    pub fn rank(mut self, rank: i16) -> Self {
472        self.rank = rank;
473        self
474    }
475
476    /// get rank of `MiddleWareBuilder`
477    ///
478    /// # Examples
479    ///
480    /// ```rust
481    /// # use dyer::middleware::*;
482    /// let middleware = MiddleWareBuilder::new()
483    ///     .rank(1)
484    ///     .build("marker");
485    /// middleware.rank_mut() = 3;
486    /// assert_eq!(middleware.rank_ref(), 3);
487    /// ```
488    pub fn rank_ref(&self) -> i16 {
489        self.rank
490    }
491
492    builder!(
493        task,
494        task,
495        handle_task,
496        Task,
497        task_ref,
498        MiddleWareBuilder::new()
499    );
500    builder!(
501        affix,
502        affix,
503        handle_affix,
504        Affix,
505        affix_ref,
506        MiddleWareBuilder::new()
507    );
508    builder!(
509        entity,
510        entity,
511        handle_entity,
512        E,
513        entity_ref,
514        MiddleWareBuilder::new()
515    );
516    builder!(
517        req,
518        req,
519        handle_req,
520        Request,
521        req_ref,
522        MiddleWareBuilder::new()
523    );
524    builder!(
525        res,
526        res,
527        handle_res,
528        Response,
529        res_ref,
530        MiddleWareBuilder::new()
531    );
532    builder!(err, err, handle_err, Result<Response, MetaResponse>, err_ref, MiddleWareBuilder::new());
533    builder!(yerr, yerr, handle_yerr, Result<Response, MetaResponse>, yerr_ref, MiddleWareBuilder::new());
534}