7 releases
Uses new Rust 2024
| 0.2.3 | Nov 27, 2025 |
|---|---|
| 0.2.2 | Nov 27, 2025 |
| 0.2.1 | Mar 26, 2025 |
| 0.2.0 | Nov 27, 2024 |
| 0.1.1 | Sep 19, 2024 |
#1147 in Asynchronous
23 downloads per month
19KB
533 lines
Pupactor is actor model library built with tokio
Macros and traits could help you to organise actors to look same
Actor body looks like:
#[derive(Pupactor)]
#[actor(cmd = "MyActorShutdown")]
struct MyFirstTestActor {
some_data: bool,
some_other_data: usize,
#[listener]
interval: Listener<Interval, Instant>,
#[listener]
interval2: Listener<Interval, Instant>,
#[listener]
channel: Listener<UnboundedReceiver<ActorMsg<Value, MyActorShutdown>>, Value, MyActorShutdown>,
}
where Pupactor macro generates select! macro that listens interval, interval2 and channel
On each income event (Interval, Value) we need create a Handle like this:
impl AsyncHandle<Instant> for MyFirstTestActor {
async fn async_handle(&mut self, _value: Instant) {
self.some_other_data += 1;
println!("New msg, counter: {}", self.some_other_data);
}
}
Or sync handle if you do not need async
impl Handle<Instant> for MyFirstTestActor {
fn handle(&mut self, _value: Instant) {
self.some_other_data += 1;
println!("New msg, counter: {}", self.some_other_data);
}
}
For more complex values like enums, there is other macro ActorMsgHandle:
#[derive(ActorMsgHandle)]
#[actor(kind = "MyFirstTestActor")]
pub enum Value {
MyGreetings(String),
U32(u32),
U64(u64),
}
So you will need describe handles only for String, u32 and u64
impl AsyncHandle<u32> for MyFirstTestActor {
async fn async_handle(&mut self, value: u32) -> Continue {
println!("New msg: {value}");
}
}
All handles can return something. All return types:
Continue - actor continue live
Cmd<T> where T is MyActorShutdown - this is your custom command
Break - this command will break the infinite loop { select!{ ... } }
Resut<Continue, Cmd<T>>
Resut<Continue, Break>
Resut<Continue, Result<Break, Cmd<T>>>
Dependencies
~2.1–5MB
~84K SLoC