1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use std::future::Future;

use crate::{context::Ctx, ActorRef, Message};

pub enum Scheduler {
    Blocking,
    NonBlocking,
}

/// User implemented actor. The user must inheriate this trait so that we can
/// control the execution of the actors struct.
pub trait Actor: Send + Sync + Sized + 'static {
    /// Return a debuggable name of the actor
    fn name() -> &'static str {
        std::any::type_name::<Self>()
    }

    /// Explain the type of scheduler the actor should use
    fn scheduler() -> Scheduler {
        Scheduler::NonBlocking
    }

    /// Declare the maximum amount of anonymous actors that a parent actor can
    /// spawn. If the maximum amount of anonymous actors are executing, then pause
    /// the actor until there is space to spawn another.
    fn max_anonymous_actors() -> usize {
        usize::MAX >> 3
    }

    /// The max size of the actors mailbox. The actor will only be able to store
    /// a max of the number provided. After the mailbox is full, it will stop
    /// accepting new message or apply back pressure and the sender will need to
    /// wait for items to be removed from the mailbox.
    fn mailbox_size() -> usize {
        6
    }

    /// Start an actor using a context
    fn start(self) -> ActorRef<Self>
    where
        Self: Actor,
    {
        Ctx::new().run(self)
    }

    /// Called before transitioning to an [`ActorState::Started`] state. Good usage is to load data
    /// from a database or disk.
    fn on_start(&mut self, _: &mut Ctx<Self>)
    where
        Self: Actor,
    {
    }

    /// Called right before the handler for the message. Basically before the actors
    /// state transitions from a [`ActorState::Started`] to a [`ActorState::Running`].
    /// Good usage is to cache data that can not be lost!
    fn pre_run(&mut self, _: &mut Ctx<Self>) {}

    /// Called after the handler for any message has been called. Is called before
    /// actor state transitions from a [`ActorState::Running`] to a [`ActorState::Started`].
    /// Good usage is logging.
    fn post_run(&mut self, _: &mut Ctx<Self>) {}

    /// Called after transitioning to an [`ActorState::Stopping`] state. Mainly
    /// used to communicate with all child actors that the actor will be shutting
    /// down shortly and that they should also finish executing.
    fn on_stopping(&mut self, _: &mut Ctx<Self>) {}

    /// Called after transitioning to an [`ActorState::Stopped`] state. Even when
    /// this state is reached there could be messages left inside of the mailbox.
    /// Users should save an actors data during the [`Actor::on_end`] state transition.
    fn on_stopped(&mut self, _: &mut Ctx<Self>) {}

    /// Called after clearing out the actors mailbox and after all child actors
    /// have been de-initialized. Good time to clean up the actor and save some
    /// of it's state.
    fn on_end(&mut self, _: &mut Ctx<Self>) {}
}

/// An internal implementation for the handler that we can implement generic behavior
/// for all actors. This would include messages for shutting down the actors, timing
/// out the actors, ect.
pub trait InternalHandler<M: Message>: Actor {
    /// Handle the message recieved by the actor
    fn private_handler(&mut self, message: M, context: &mut Ctx<Self>);
}

/// Handler is able to be programmed to handle certian messages. When executing
/// it can answer messages or it can forward them to new actors. Special care
/// must be taken when forwarding a message from an actor. When forwarding,
/// a user can return None.
///
/// However, when responding to a message, it is required to return a message
/// inside of the option. If no response is found, an error is triggered and
/// the request is complete with an error.
pub trait Handler<M: Message>: Actor {
    /// this method is called for every message received by the actor
    fn handle(&mut self, message: M, context: &mut Ctx<Self>);
}

/// Ask an actor to handle a message but also return a response. Asking is an
/// optimization to be able to handle two operations at once.
pub trait Ask<M: Message>: Actor {
    type Result: Message;

    fn handle(&mut self, message: M, context: &mut Ctx<Self>) -> Self::Result;
}

/// Ask an actor to recieve a message and respond back. The respond is expected to
/// be some type of async operation and thus is executed by a anonymous actor that
/// takes one messages and handles it.
pub trait AsyncAsk<M: Message>: Actor {
    type Output: Message;
    type Future<'a>: Future<Output = Self::Output> + Send + Sync + 'a;

    fn handle<'a>(&'a mut self, message: M, context: &mut Ctx<Self>) -> Self::Future<'a>;
}