elfo_core/routers/
mod.rs

1use std::{
2    fmt::{self, Display},
3    hash::Hash,
4};
5
6use elfo_macros::msg_raw as msg;
7
8use crate::{self as elfo, envelope::Envelope};
9
10pub use self::map::MapRouter;
11
12mod map;
13
14pub trait Router<C>: Send + Sync + 'static {
15    type Key: Clone + Hash + Eq + Display + Send + Sync; // TODO: why is `Sync` required?
16
17    fn update(&self, _config: &C) {}
18    fn route(&self, envelope: &Envelope) -> Outcome<Self::Key>;
19}
20
21/// Specifies which actors will get a message.
22#[derive(Debug)]
23#[non_exhaustive]
24pub enum Outcome<T> {
25    /// Routes a message to an actor with the specified key.
26    /// If there is no active or restarting actor for this key,
27    /// it will be started.
28    Unicast(T),
29    /// Routes a message to an actor with the specified key.
30    /// If there is no active or restarting actor for this key,
31    /// the message will be discarded, no actors are started.
32    GentleUnicast(T),
33    /// Routes a message to all actors with specified keys.
34    /// If there is no active or restarting actors for these keys,
35    /// they will be started.
36    Multicast(Vec<T>),
37    /// Routes a message to all actors with specified keys.
38    /// If there is no active or restarting actors for these keys,
39    /// the message will be descarded, no actors are started.
40    GentleMulticast(Vec<T>),
41    /// Routes a message to all active actors.
42    Broadcast,
43    /// Discards a message.
44    /// If a message is discarded by everyone, the sending side gets an error.
45    Discard,
46    /// Acts as `Broadcast` for system messages and `Discard` otherwise.
47    Default,
48}
49
50assert_eq_size!(Outcome<u64>, [u8; 32]);
51assert_eq_size!(Outcome<u128>, [u8; 32]);
52
53impl<T> Outcome<T> {
54    /// Transforms `Unicast` and `Multicast` variants.
55    #[inline]
56    pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Outcome<U> {
57        match self {
58            Outcome::Unicast(val) => Outcome::Unicast(f(val)),
59            Outcome::GentleUnicast(val) => Outcome::GentleUnicast(f(val)),
60            Outcome::Multicast(list) => Outcome::Multicast(list.into_iter().map(f).collect()),
61            Outcome::GentleMulticast(list) => {
62                Outcome::GentleMulticast(list.into_iter().map(f).collect())
63            }
64            Outcome::Broadcast => Outcome::Broadcast,
65            Outcome::Discard => Outcome::Discard,
66            Outcome::Default => Outcome::Default,
67        }
68    }
69
70    /// Replaces the `Default` variant with the provided one.
71    #[inline]
72    pub fn or(self, outcome: Outcome<T>) -> Self {
73        match self {
74            Outcome::Default => outcome,
75            _ => self,
76        }
77    }
78}
79
80impl<C> Router<C> for () {
81    type Key = Singleton;
82
83    #[inline]
84    fn route(&self, envelope: &Envelope) -> Outcome<Self::Key> {
85        use crate::messages::*;
86
87        msg!(match envelope {
88            // These messages shouldn't spawn actors.
89            // TODO: maybe this logic should be in the supervisor.
90            ValidateConfig | Terminate | Ping => Outcome::GentleUnicast(Singleton),
91            _ => Outcome::Unicast(Singleton),
92        })
93    }
94}
95
96/// A key used for actor groups containing only one actor.
97#[derive(Debug, Clone, Hash, PartialEq, Eq)]
98pub struct Singleton;
99
100impl fmt::Display for Singleton {
101    #[inline]
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        // If this line is changed, change also a key in `start.rs` to be consistent.
104        f.write_str("_")
105    }
106}