chikatetsu 0.1.0

An(other) actor framework for Tokio
Documentation
use tokio::sync::*;

use async_trait::async_trait;

use std::marker::PhantomData;

use crate::message::*;

#[async_trait]
pub trait Actor: Sized + Send + 'static {
    type MessageGroup: MessageGroup;

    async fn handle_all(
        &mut self,
        msg: Self::MessageGroup,
    ) -> <Self::MessageGroup as MessageGroup>::ReplyGroup;
    fn start(mut self) -> ActorHandle<Self> {
        let (sender, mut rx) = mpsc::channel(32);
        let handle = ActorHandle {
            sender,
            _actor: PhantomData,
        };

        tokio::spawn(async move {
            while let Some((msg, tx_reply)) = rx.recv().await {
                let _ = tx_reply.send(self.handle_all(msg).await);
            }
        });

        handle
    }
}

#[derive(Clone)]
pub struct ActorHandle<A: Actor> {
    sender: mpsc::Sender<(
        A::MessageGroup,
        oneshot::Sender<<A::MessageGroup as MessageGroup>::ReplyGroup>,
    )>,
    _actor: PhantomData<A>,
}

impl<A: Actor> ActorHandle<A> {
    pub async fn send<M, R>(&self, msg: M) -> R
    where
        M: Message<Group = A::MessageGroup, Reply = R>,
        R: Reply<Group = <A::MessageGroup as MessageGroup>::ReplyGroup>,
    {
        let (tx, rx) = oneshot::channel();
        let _ = self.sender.send((msg.to_group(), tx)).await;
        R::from_group(rx.await.unwrap()).unwrap()
    }
}