The murray
crate provides a actor
macro that helps defining erlang inspired actors. The actor is targeted at async and tokio but can be adapted by use
ing other mpsc
channels.
```
actor! {
Foo,
Messages: {
Msg1,
Msg2,
Msg3 { ch: mpsc::Receiver
impl FooActor { fn handle(&self, state: &mut FooActorState, msg: FooActorMessages) -> () { () }
}
actor! { Bar, Options: { sup: Foo, id: String, }, Messages: { A, B { x: bool, }, }, State: { foo: TypeC, } }
impl FooActor { async fn handlemsg1(&self, state: &mut FooActorState) { ... } async fn handlemsg2(&self, state: &mut FooActorState) { ... } async fn handle_msg3(&self, state: &mut FooActorState, msg: FooActorMessagesMsg3) { ... } }
impl BarActor { async fn handlea(&self, state: &mut BarActorState) { ... } async fn handleb(&self, state: &mut BarActorState, msg: BarActorMessagesB) { ... } }
let sup = FooActor{}.start(); let id = String::from("abar"); let abar = BarActor{}.start(sup, &id);
abar.send(BarActorMessages::B(true));
```
This will produce struct FooActor
, enum FooActorMessages
and a struct FooActorState
(and similar for Bar).
If you include Options
they may include a sup
naming the agent's supervisor and a id
naming the type of actors id. The type must be Clone.
The State struct includes a tx
Sender
channel so that your handlers can send messages back to the actor. If the actor has a supervisor it will also include a sup_ch
and an id
field if it's included in options. The actor definition includes a State
with extra properties they will be included in the state struct as Option
initialized to None.
The macro expands message variants with propreties into corresponding struct
with the propreties for easier handling in handler functions. So for Foo
the macro generates a struct FooActorMessagesMsg3
but no struct FooActorMessagesMsg1
or 2 and expects you to provide FooActor::handle_msg1
, FooActor::handle_msg2
and FooActor::handle_msg3
. The handler functions are async
and return ()
. All communication with the actor is done via state.tx
.