Crate actor_helper

Crate actor_helper 

Source
Expand description

Lightweight, runtime-agnostic actor pattern with dynamic error types.

Works with tokio, async-std, or blocking threads. Uses flume channels.

§Quick Start

use std::io;
use actor_helper::{Actor, Handle, Receiver, act_ok, spawn_actor};

// Public API
pub struct Counter {
    handle: Handle<CounterActor, io::Error>,
}

impl Counter {
    pub fn new() -> Self {
        let (handle, rx) = Handle::channel();
        spawn_actor(CounterActor { value: 0, rx });
        Self { handle }
    }

    pub async fn increment(&self, by: i32) -> io::Result<()> {
        self.handle.call(act_ok!(actor => async move {
            actor.value += by;
        })).await
    }

    pub async fn get(&self) -> io::Result<i32> {
        self.handle.call(act_ok!(actor => async move { actor.value })).await
    }
}

// Private actor
struct CounterActor {
    value: i32,
    rx: Receiver<actor_helper::Action<CounterActor>>,
}

impl Actor<io::Error> for CounterActor {
    async fn run(&mut self) -> io::Result<()> {
        loop {
            tokio::select! {
                Ok(action) = self.rx.recv_async() => action(self).await,
            }
        }
    }
}

§Error Types

Use any error type implementing ActorError:

  • io::Error (default)
  • anyhow::Error (with anyhow feature)
  • String
  • Box<dyn Error>

§Blocking/Sync

use actor_helper::{ActorSync, block_on};

impl ActorSync<io::Error> for CounterActor {
    fn run_blocking(&mut self) -> io::Result<()> {
        loop {
            if let Ok(action) = self.rx.recv() {
                block_on(action(self));
            }
        }
    }
}

// Use call_blocking instead of call
handle.call_blocking(act_ok!(actor => async move { actor.value }))?;

§Notes

  • Actions run sequentially, long tasks block the mailbox
  • Panics are caught and converted to errors with location info
  • call requires tokio or async-std feature
  • call_blocking has no feature requirements

Macros§

act
Create action returning Result<T, E>.
act_ok
Create action returning T, auto-wrapped as Ok(T).

Structs§

Handle
Cloneable handle to send actions to actor A with error type E.

Traits§

ActorError
Convert panic/actor-stop messages into your error type.
ActorSync
Blocking actor trait. Loop receiving actions with recv() and executing them with block_on().

Functions§

block_on
Execute async futures in blocking context. Required for ActorSync. Run a future to completion on the current thread.
spawn_actor_blocking
Spawn blocking actor on new thread.

Type Aliases§

Action
Action sent to an actor: FnOnce(&mut A) -> Future<()>.
ActorFut
Pinned, boxed future used by action helpers and macros.
PreBoxActorFut
Unboxed future type for actor actions.
Receiver
Flume unbounded receiver. Actors receive actions via Receiver<Action<Self>>.
Sender
Flume unbounded sender.