Coerce-rs is an asynchronous (async/await) Actor runtime and distributed system framework for Rust. It allows for extremely simple yet powerful actor-based distributed system development. With minimal code, you can build a highly scalable, fault-tolerant modern actor-driven application.
ActorRef<A>
types (ActorRef may comprise of a LocalActorRef<A>
or a RemoteActorRef<A>
)Building Coerce is easy. All you need is the latest Rust stable or nightly installed, along with Cargo. ```shell
git clone https://github.com/leonhartley/coerce-rs && cd coerce-rs
cargo build
cargo test ```
Every actor belongs to an ActorSystem.
An actor is just another word for a unit of computation. It can have mutable state, it can receive messages and perform
actions. One caveat though.. It can only do one thing at a time. This can be useful because it can alleviate the need
for thread synchronisation, usually achieved by locking (using Mutex
, RwLock
etc).
Coerce uses Tokio's MPSC channels (tokio::sync::mpsc::channel), every actor created spawns a task listening
to messages from a
Receiver
, handling and awaiting the result of the message. Every reference (ActorRef<A: Actor>
) holds
a Sender<M> where A: Handler<M>
, which can be cloned.
Actors can be stopped and actor references can be retrieved by ID from anywhere in your application. IDs are String
but if an ID isn't provided upon creation, a new Uuid
will be generated. Anonymous actors are automatically dropped (
and Stopped
)
when all references are dropped. Tracked actors (using global fn new_actor
) must be stopped.
Basic ActorSystem + EchoActor example
```rust pub struct EchoActor {}
impl Actor for EchoActor {}
pub struct EchoMessage(String);
impl Message for EchoMessage { type Result = String; }
impl Handler
pub async fn run() { let mut actor = new_actor(EchoActor {}).await.unwrap();
let helloworld = "hello, world".tostring(); let result = actor.send(EchoMessage(hello_world.clone())).await;
asserteq!(result, Ok(helloworld)); } ```
```rust pub struct EchoActor {}
impl Actor for EchoActor {}
pub struct EchoMessage(String);
impl Message for EchoMessage { type Result = String; }
pub struct PrintTimer(String);
impl TimerTick for PrintTimer {}
impl Handler
pub async fn run() { let mut actor = newactor(EchoActor {}).await.unwrap(); let helloworld = "hello world!".to_string();
// print "hello world!" every 5 seconds let timer = Timer::start(actor.clone(), Duration::fromsecs(5), TimerTick(helloworld));
// timer is stopped when handle is out of scope or can be stopped manually by calling .stop()
sleep(Duration::from_secs(20)).await;
timer.stop();
}
```