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
use crate::actors_manager::ActorsManager; use crate::system_director::SystemDirector; use crate::{Actor, Receive, Respond}; use async_std::task; use std::fmt::Debug; /// This object is provided to the handle method in the [Receive](./trait.Receive.html) trait for each message /// that an Actor receives. The Actor's assistant allows to send messages and to execute some task over the system. /// /// ```rust,no_run /// # use acteur::{Actor, Receive, Assistant, Acteur}; /// # use async_trait::async_trait; /// # /// # #[derive(Debug)] /// # struct Employee { /// # salary: u32, /// # manager_id: u32, /// # } /// # /// # #[async_trait] /// # impl Actor for Employee { /// # type Id = u32; /// # /// # async fn activate(_: Self::Id) -> Self { /// # Employee { /// # salary: 0, // Load from DB or set a default, /// # manager_id: 0 , /// # } /// # } /// # } /// # /// # #[derive(Debug)] /// # struct Manager; /// # /// # #[async_trait] /// # impl Actor for Manager { /// # type Id = u32; /// # /// # async fn activate(_: Self::Id) -> Self { /// # Manager /// # } /// # } /// # #[async_trait] /// # impl Receive<SayByeForever> for Manager { /// # async fn handle(&mut self, message: SayByeForever, assistant: &Assistant<Manager>) {} /// # } /// #[derive(Debug)] /// struct SalaryChanged(u32); /// /// #[derive(Debug)] /// struct SayByeForever(String); /// /// #[async_trait] /// impl Receive<SalaryChanged> for Employee { /// async fn handle(&mut self, message: SalaryChanged, assistant: &Assistant<Employee>) { /// if self.salary > message.0 { /// assistant.send::<Manager, SayByeForever>(self.manager_id, SayByeForever("Betrayer!".to_string())); /// } /// /// self.salary = message.0; /// } /// } /// /// # fn main() { /// # let sys = Acteur::new(); /// # /// # sys.send_sync::<Employee, SalaryChanged>(42, SalaryChanged(55000)); /// # /// # sys.wait_until_stopped(); /// # } /// /// ``` /// pub struct Assistant<A: Actor> { system_director: SystemDirector, actor_id: A::Id, manager: ActorsManager<A>, } impl<A: Actor> Assistant<A> { pub(crate) fn new( system_director: SystemDirector, manager: ActorsManager<A>, actor_id: A::Id, ) -> Assistant<A> { Assistant { system_director, actor_id, manager, } } /// Sends a message to the Actor with the specified Id. /// If the Actor is not loaded, it will load the actor before, calling its method `activate` pub async fn send<A2: Actor + Receive<M>, M: Debug + Send + 'static>( &self, actor_id: A2::Id, message: M, ) { self.system_director.send::<A2, M>(actor_id, message).await } /// Sends a message to the Actor with the specified Id and waits the actor's response . /// If the Actor is not loaded, it will load the actor before, calling its method `activate` pub async fn call<A2: Actor + Respond<M>, M: Debug + Send + 'static>( &self, actor_id: A2::Id, message: M, ) -> Result<<A2 as Respond<M>>::Response, &str> { self.system_director.call::<A2, M>(actor_id, message).await } /// Enqueues a end command in the Actor messages queue. The actor will consume all mesages before ending. /// Keep in mind that event is an actor is stopped, a new message in the future can wake up the actor. pub async fn stop(&self) { self.system_director .stop_actor::<A>(self.actor_id.clone()) .await; } /// Send an stop message to all actors in the system. /// Actors will process all the enqued messages before stop pub fn stop_system(&self) { let system = self.system_director.clone(); task::spawn(async move { system.stop().await; }); } } impl<A: Actor> Clone for Assistant<A> { fn clone(&self) -> Self { Assistant { system_director: self.system_director.clone(), actor_id: self.actor_id.clone(), manager: self.manager.clone(), } } } impl<A: Actor> Debug for Assistant<A> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "ActorSecretary for {}", std::any::type_name::<A>()) } }