elfo_core/routers/
map.rs

1use std::{fmt::Display, hash::Hash, marker::PhantomData, sync::Arc};
2
3use arc_swap::ArcSwap;
4
5use super::{Outcome, Router};
6use crate::envelope::Envelope;
7
8pub struct MapRouter<C, S, P, R> {
9    config: PhantomData<C>,
10    state: S,
11    prepare: P,
12    route: R,
13}
14
15// Just router.
16impl<C, R, K> MapRouter<C, (), (), R>
17where
18    C: Send + Sync + 'static,
19    R: Fn(&Envelope) -> Outcome<K> + Send + Sync + 'static,
20{
21    #[inline]
22    pub fn new(route: R) -> Self {
23        Self {
24            config: PhantomData,
25            state: (),
26            prepare: (),
27            route,
28        }
29    }
30}
31
32impl<C, R, K> Router<C> for MapRouter<C, (), (), R>
33where
34    C: Send + Sync + 'static,
35    R: Fn(&Envelope) -> Outcome<K> + Send + Sync + 'static,
36    K: Clone + Hash + Eq + Display + Send + Sync,
37{
38    type Key = K;
39
40    #[inline]
41    fn route(&self, envelope: &Envelope) -> Outcome<Self::Key> {
42        (self.route)(envelope)
43    }
44}
45
46// With state.
47impl<C, S, P, R, K> MapRouter<C, ArcSwap<S>, P, R>
48where
49    C: Send + Sync + 'static,
50    S: Default + Send + Sync + 'static,
51    R: Fn(&Envelope, &S) -> Outcome<K> + Send + Sync + 'static,
52    P: Fn(&C, &S) -> S + Send + Sync + 'static,
53{
54    #[inline]
55    pub fn with_state(prepare: P, route: R) -> Self {
56        Self {
57            config: PhantomData,
58            state: ArcSwap::default(),
59            prepare,
60            route,
61        }
62    }
63}
64
65impl<C, S, P, R, K> Router<C> for MapRouter<C, ArcSwap<S>, P, R>
66where
67    C: Send + Sync + 'static,
68    S: Send + Sync + 'static,
69    R: Fn(&Envelope, &S) -> Outcome<K> + Send + Sync + 'static,
70    P: Fn(&C, &S) -> S + Send + Sync + 'static,
71    K: Clone + Hash + Eq + Display + Send + Sync,
72{
73    type Key = K;
74
75    #[inline]
76    fn update(&self, config: &C) {
77        self.state
78            .rcu(|state| Arc::new((self.prepare)(config, state)));
79    }
80
81    #[inline]
82    fn route(&self, envelope: &Envelope) -> Outcome<Self::Key> {
83        let state = self.state.load();
84        (self.route)(envelope, &state)
85    }
86}