Actor capable of handling multiple messages concurrently
I've been thinking about this and I think this could be useful.
The problem
Currently, writing something like this
impl Handler<Event, MyMessage> for MyActor {
async fn handle(&mut self, msg: MyMessage, _ctx: &mut ActorContext) -> () {
println!("{:?}", msg);
// Some long blocking operation
tokio::time::sleep(Duration::from_secs(5)).await
}
}
causes the actor to longer accept new messages. There could be cases where this is not desired, and the user wants to handle messages concurrently and lock datastructures internally.
Possible solution
There could be a MultiHandler trait, similar to Handler, and an additional create_multi_actor function that gives the system a number of runners.
I have implemented a simple system that does this in my fork at https://github.com/NotAPenguin0/tiny-tokio-actor. Please let me know if this is a reasonable feature or not something that fits in the actor model and other solutions should be used. In my implementation, the MultiHandler trait is marked unsafe to signify that there is no synchronization provided for the actor's internal state.
Thanks for this issue @NotAPenguin0! It's indeed a problem that an actor can block and then stop processing messages. My initial hunch would be to implement something akin to Akka's actor routers whereby you can pool a bunch of blocking actors, all consuming from the same mailbox as it where. Your implementation is almost similar, but I think its better if the Actor itself is kept very simple (and blocking) while we add a Router like in Akka. To do this properly though you do need parent/child supervision which is not implemented (yet!).
Thanks for the reply! Adding a proper router seems like a much cleaner solution yeah. It would also solve the safety issue my current implementation has. I'll ponder a bit on it and see if I can try to get something working.