riker-rs / riker

Easily build efficient, highly concurrent and resilient applications. An Actor Framework for Rust.
https://riker.rs
MIT License
1.02k stars 69 forks source link

Infinite loop for1 actor will hang all system #81

Open DAOCUONG opened 4 years ago

DAOCUONG commented 4 years ago

For my understanding about actor model, i need 1 actor keep looping to do some task it should not hang the system, other actors should still working and do their job

hardliner66 commented 4 years ago

If you infinitly loop inside an actor, you block one thread of the threadpool. If you infinitly loop in more actors than there are threads in the threadpool, the system hangs because it can't process any other messages. So it would be better to not infinetly loop inside an actor.

But this is a problem with threadpools and not with the actor model itself.

If you need something that would block, you should move that into another thread, outside of the threadpool.

If you need to do (or check) something repeatedly then you can create an actor and use the pre_start start method to schedule a message every X milliseconds to perform your operation. e.g.:

#[derive(Debug, Clone)]
enum Message {
    Loop,
    Str(String),
}

// implement the Actor trait
impl Actor for MyActor {
    type Msg = Message;

    fn pre_start(&mut self, ctx: &Context<Message>) {
        ctx.schedule(
            Duration::from_secs(0),      // initial delay
            Duration::from_millis(1000), // time between messages
            ctx.myself.clone(),
            None,
            Message::Loop, // your loop message
        );
    }

    fn recv(&mut self, ctx: &Context<Message>, msg: Message, _sender: Sender) {
        match msg {
            Message::Loop => {
                // do something repeatedly
                println!(
                    "[{}]({:?}) LOOP",
                    ctx.myself().path(),
                    std::thread::current().id()
                );
            }
            Message::Str(s) => {
                // do something with the Str message
                println!(
                    "[{}]({:?}) :: Received: \"{}\", self.value: {}",
                    ctx.myself().path(),
                    std::thread::current().id(),
                    s,
                    self.value
                );
            }
        }
    }
}

This way the actor can still respond to other messages, while repeatedly responding to the scheduled message.

leenozara commented 4 years ago

Keeping this open for now because it’s a common occurrence and the explanation and solution provided by @hardliner66 is very good. We’ll get this included in the official docs and close this issue after.