Is it possible to use the Akka scheduler inside an actor?

Felix Reckers picture Felix Reckers · Dec 15, 2012 · Viewed 10.6k times · Source

I want to have the possibility to put actors to sleep for a while. The actors should decide themselves how long they are going to sleep. As Thread.sleep() is not a recommended way of doing this I thought of using the scheduler in akka. I therefore defined an actor were another actor can register for being woken up.

class Scheduler extends Actor {

  def receive = {
    case Sleep(duration) => context.system.scheduler.scheduleOnce(duration) {
      sender ! Ring
    }
  }
}

But the sending actor never receives the Ring message. So my questions are

  • Is scheduling with the scheduler recommended inside an actor?
  • Why is the sending actor never receiving the Ring message?
  • If this is not possible what is the recommended way of solving the problem?

Answer

Roland Kuhn picture Roland Kuhn · Dec 16, 2012

Let me first answer the title question: yes, it is possible to use the scheduler inside an actor.

case Sleep(duration) =>
  context.system.scheduler.scheduleOnce(duration, self, Ring)

Now to the question behind the question

You did not say what you actually want to achieve, so I’m making an educated guess here that you want the actor—which normally does something called “X”—to do something called “Y” for a while, suspending the “X” activity. The full solutions to this would be

class Sleepy extends Actor {
  def receive = {

    ... // cases doing “X”

    case Sleep(duration) =>
      case object WakeUp
      context.system.scheduler.scheduleOnce(duration, self, WakeUp)
      context.become({
        case WakeUp => context.unbecome()
        // drop the rest
      }, discardOld = false)
  }
}

The same could as well be implemented using the FSM trait and switching between the normal and the sleeping state. And of course you can do whatever you want while sleeping, e.g. mix in the Stash trait in Akka 2.1 and call stash() for all (or some) messages while sleeping, unstashAll() when getting the WakeUp message; or you could do something else altogether. Actors are very flexible.

What actors don’t do

Actors never really sleep, they always handle incoming messages. As shown above, you can define what that means, but the basic principle is that you cannot suspend an actor such that it will not process the messages in its mailbox.