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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use crate::Actor;
use crate::ActorAssistant;
use async_trait::async_trait;
use std::fmt::Debug;

/// This Trait allow Actors to receive messages. This is the most efficient way to process messages as it doesn't
/// require to respond the message.
///
/// If you want to respond to messages, use the [Respond trait](./trait.Respond.html).
///
/// This trait is compatible with [Respond trait](./trait.Respond.html) as you can implement, for the same message,
/// both traits. This trait will be executed when using the "send_to_actor" or "send_to_actor_sync" method from System
/// or the "send_to_actor" method from ActorAssistant.
///
/// ```rust,no_run
/// use async_trait::async_trait;
/// # use acteur::{Actor};
/// # #[derive(Debug)]
/// # struct Employee {
/// #     id: u32,
/// #     salary: u32,
/// # }
/// #
/// # #[async_trait]
/// # impl Actor for Employee {
/// #     type Id = u32;
/// #
/// #     async fn activate(id: Self::Id, _: &ActorAssistant<Self>) -> Self {
/// #         println!("Employee {:?} activated!", id);
/// #         Employee {
/// #             id,
/// #             salary: 0 //Load from DB, set a default, etc
/// #         }
/// #     }
/// #
/// #     async fn deactivate(&mut self) {
/// #         println!("Employee {:?} deactivated!", self.id);
/// #     }
/// # }
/// use acteur::{ActorAssistant, Receive, Acteur};
///
/// #[derive(Debug)]
/// struct SalaryChanged(u32);
///
/// #[async_trait]
/// impl Receive<SalaryChanged> for Employee {
///     async fn handle(&mut self, message: SalaryChanged, _: &ActorAssistant<Employee>) {
///         self.salary = message.0;
///     }
/// }
///
/// fn main() {
///     let sys = Acteur::new();
///
///     sys.send_to_actor_sync::<Employee, SalaryChanged>(42, SalaryChanged(55000));
///
///     sys.wait_until_stopped();
/// }
///
/// ```
///
///
#[async_trait]
pub trait Receive<M: Debug>
where
    Self: Sized + Actor,
{
    /// This method is called each time a message is received.
    /// You can use the [ActorAssistant](./struct.ActorAssistant.html) to send messages from actors,
    /// [`System`](./struct.System.html) to send messages from services and
    /// [`Acteur`](./struct.System.html) to send messages from outside the framework
    async fn handle(&mut self, message: M, assistant: &ActorAssistant<Self>);
}

/// This Trait allow Actors to receive messages and, additionally, respond to them.
///
/// This trait is like the [Receive trait](./trait.Receive.html) but additionally allows responding to messages
///
/// This trait is compatible with [Receive trait](./trait.Receive.html) as you can implement, for the same message,
/// both traits. This trait will be executed when using the "call_actor" or "call_actor_sync" method from System or
/// the "call_actor" method from ActorAssistant.
///
/// ## Note about concurrency and performance
///
/// If there is no reason to respond to a message, prefer to use the [Receive trait](./trait.Receive.html) trait, as
/// this may delay you Actors or even deadlock them. For example:
///
///  1. Actor A-51 calls Actor B-32
///  2. Actor B-32 calls Actor A-51
///
/// As Actor A-51 is blocked waiting for B-32, this will keep waiting forever.
///
/// Additionally, all the time waiting for a response, is time that the Actor instance won't be processing messages.
/// Keep this in mind as if you call to a very busy instance, that may slow down other instance, making the first wait
/// until the busy ones processes all the messages before yours.
///
/// ```rust,no_run
/// use async_trait::async_trait;
/// # use acteur::{Actor};
/// # #[derive(Debug)]
/// # struct Employee {
/// #     id: u32,
/// #     salary: u32,
/// # }
/// #
/// # #[async_trait]
/// # impl Actor for Employee {
/// #     type Id = u32;
/// #
/// #     async fn activate(id: Self::Id, _: &ActorAssistant<Self>) -> Self {
/// #         println!("Employee {:?} activated!", id);
/// #         Employee {
/// #             id,
/// #             salary: 0 //Load from DB, set a default, etc
/// #         }
/// #     }
/// #
/// #     async fn deactivate(&mut self) {
/// #         println!("Employee {:?} deactivated!", self.id);
/// #     }
/// # }
/// use acteur::{ActorAssistant, Respond, Acteur};
///
/// #[derive(Debug)]
/// struct SalaryChanged(u32);
///
/// #[async_trait]
/// impl Respond<SalaryChanged> for Employee {
///     type Response = String;
///     async fn handle(&mut self, message: SalaryChanged, _: &ActorAssistant<Employee>) -> String {
///         self.salary = message.0;
///         String::from("Thanks!")
///     }
/// }
///
/// fn main() {
///     let sys = Acteur::new();
///
///     let response = sys.call_actor_sync::<Employee, SalaryChanged>(42, SalaryChanged(55000));
///
///     println!("Response is: {:?}", response); // Response is: Thanks!
///
///     sys.wait_until_stopped();
/// }
///
/// ```
///
/// You can use the [ActorAssistant](./struct.ActorAssistant.html) in order to interact with other actors and the system.
///
///
#[async_trait]
pub trait Respond<M: Debug>: Sized + Actor {
    type Response: Send;
    /// This method is called each time a message is received.
    /// You can use the [ActorAssistant](./struct.ActorAssistant.html) to send messages from actors,
    /// [`System`](./struct.System.html) to send messages from services and
    /// [`Acteur`](./struct.System.html) to send messages from outside the framework
    async fn handle(&mut self, message: M, assistant: &ActorAssistant<Self>) -> Self::Response;
}