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; }