speare 0.4.3

actor-like thin abstraction over tokio::task and flume channels
Documentation
mod sync_vec;
use speare::{Actor, Ctx, Node};
use sync_vec::SyncVec;
use tokio::task;

#[derive(Debug, PartialEq, Clone, Copy)]
enum TestMsg {
    Foo,
    Bar,
}

struct Foo;

impl Actor for Foo {
    type Props = SyncVec<TestMsg>;
    type Msg = TestMsg;
    type Err = ();

    async fn init(_: &mut Ctx<Self>) -> Result<Self, Self::Err> {
        Ok(Foo)
    }

    async fn handle(&mut self, msg: Self::Msg, ctx: &mut Ctx<Self>) -> Result<(), Self::Err> {
        ctx.props().push(msg).await;
        Ok(())
    }
}

struct Bar;

impl Actor for Bar {
    type Props = SyncVec<TestMsg>;
    type Msg = TestMsg;
    type Err = ();

    async fn init(_: &mut Ctx<Self>) -> Result<Self, Self::Err> {
        Ok(Bar)
    }

    async fn handle(&mut self, msg: Self::Msg, ctx: &mut Ctx<Self>) -> Result<(), Self::Err> {
        ctx.props().push(msg).await;
        Ok(())
    }
}

#[tokio::test]
async fn sends_msgs_in_correct_order() {
    // Arrange
    let mut node = Node::default();
    let recvd: SyncVec<_> = Default::default();
    let foo = node.actor::<Foo>(recvd.clone()).spawn();
    let bar = node.actor::<Bar>(recvd.clone()).spawn();

    // Act
    foo.send(TestMsg::Foo);
    bar.send(TestMsg::Bar);
    task::yield_now().await;

    // Assert
    assert_eq!(vec![TestMsg::Foo, TestMsg::Bar], recvd.clone_vec().await)
}

#[tokio::test]
async fn send_returns_true_when_actor_alive() {
    let mut node = Node::default();
    let recvd: SyncVec<_> = Default::default();
    let foo = node.actor::<Foo>(recvd).spawn();

    assert!(foo.send(TestMsg::Foo));
}

#[tokio::test]
async fn send_returns_false_when_actor_stopped() {
    let mut node = Node::default();
    let recvd: SyncVec<_> = Default::default();
    let foo = node.actor::<Foo>(recvd).spawn();

    foo.stop();
    task::yield_now().await;
    assert!(!foo.send(TestMsg::Foo));
}