tractor 0.0.6

Actor system modelled after Pony's actors
Documentation
use async_trait::async_trait;
use std::time::Duration;
use tokio::time::sleep;
use tractor::prelude::*;

struct Accumulator {
    sum: usize,
}

enum AccumulatorMsg {
    Add { a: usize },
    Sub { a: usize },
}

impl Actor for Accumulator {
    type Msg = AccumulatorMsg;
}

#[async_trait]
impl ActorBehaviorAsync for Accumulator {
    async fn handle(&mut self, msg: AccumulatorMsg, _: &Context<Self>) {
        match msg {
            AccumulatorMsg::Add { a } => self.sum += a,
            AccumulatorMsg::Sub { a } => self.sum -= a,
        }
    }
}

#[async_trait]
impl ActorHooksAsync for Accumulator {
    async fn stopped(&mut self) {
        println!("Final sum: {}", self.sum);
    }
}

#[derive(Clone)]
struct Accum(Addr<Accumulator>);

impl Accum {
    fn overloaded(&self) -> bool {
        self.0.len() > 1000
    }

    fn add(&self, a: usize) {
        self.0.send(AccumulatorMsg::Add { a });
    }

    fn sub(&self, a: usize) {
        self.0.send(AccumulatorMsg::Sub { a });
    }
}

struct Feeder;

impl Actor for Feeder {
    type Msg = (usize, Accum);
}

#[async_trait]
impl ActorBehaviorAsync for Feeder {
    async fn handle(&mut self, (num, addr): (usize, Accum), _: &Context<Self>) {
        for _i in 0..num {
            while addr.overloaded() {
                sleep(Duration::from_millis(1)).await;
                // println!("Overload");
            }
            addr.add(1);
        }
    }
}

#[async_trait]
impl ActorHooksAsync for Feeder {}

fn run() {
    let accum = Accum(Accumulator { sum: 0 }.start());
    let feeder = Feeder.start();

    feeder.send((1_000_000, accum));
}

fn main() {
    ActorSystem::run_to_completion(run);
}