use tokio::sync::{mpsc, oneshot};
use crate::{message::Envelope, Context, Error, Handler, Message};
#[derive(Debug)]
pub struct Addr<A: Actor> {
msg_tx: mpsc::Sender<Envelope<A>>,
}
impl<A: Actor> Clone for Addr<A> {
fn clone(&self) -> Self {
Addr {
msg_tx: self.msg_tx.clone(),
}
}
}
impl<A: Actor> Addr<A> {
pub async fn send<M>(&self, msg: M) -> Result<M::Result, Error>
where
A: Handler<M>,
M: Message + 'static,
{
let (result_tx, result_rx) = oneshot::channel();
self.msg_tx
.send(Envelope::message_rsvp(msg, result_tx))
.await
.map_err(|_| Error::ReceiverShutdown)?;
Ok(result_rx.await.map_err(|_| Error::ReceiverShutdown)?)
}
pub(crate) async fn send_and_forget<M>(&self, msg: M) -> Result<(), Error>
where
A: Handler<M>,
M: Message + 'static,
{
self.msg_tx
.send(Envelope::message(msg))
.await
.map_err(|_| Error::ReceiverShutdown)
}
pub async fn stop(self) -> Result<A, Error> {
let (tx, rx) = oneshot::channel();
self.msg_tx
.send(Envelope::stop(tx))
.await
.map_err(|_| Error::ReceiverShutdown)?;
Ok(rx.await.map_err(|_| Error::ReceiverShutdown)?)
}
}
pub trait Actor: Sized + Send + 'static {
fn started(&mut self, _ctx: &mut Context<Self>) {}
fn stopped(&mut self) {}
fn start(self) -> Addr<Self> {
let (msg_tx, msg_rx) = mpsc::channel(10);
let addr = Addr { msg_tx };
Context::start(self, addr.clone(), msg_rx);
addr
}
}