Reputation: 34934
I want to make an actor sleep for a while, specifically it should decide whether to sleep itself depending on a condition:
class MyActor extends Actor {
def receive {
case "doWork" => doWork()
}
def doWork(): Unit = {
// doing some work
val condition = calculateCondition
if (condition) {
// sleep for 5 seconds
// Thread.sleep(5000)
}
}
}
I'm pretty much sure it's not a good thing to call Thread.sleep(5000)
inside an actor and there should be another way. Therefore, how do I make it sleep?
Upvotes: 2
Views: 695
Reputation: 15074
I would look to do this using changes of state/behaviour for the Actor. Akka gives you a couple of means of doing this: you can implement a full-on state machine, or make use of context.become
(and mix in akka.actor.Stash
), and have the actor pass (scheduled) messages to itself. The former feels like overkill for this case, so here is how I would look to code it up:
import akka.actor._
import scala.concurrent.duration._
class MySleepyActor(duration: FiniteDuration = (5 seconds)) extends Actor with Stash {
import context._
override def preStart() { become(running) }
def receive = PartialFunction.empty
def running: Actor.Receive = {
case "doWork" =>
if (doWork()) {
scheduleReactivate
become(paused)
}
case "wakeUp" => // already awake
}
def paused: Actor.Receive = {
case "doWork" => stash()
case "wakeUp" =>
unstashAll()
become(running)
}
def scheduleReactivate: Unit = {
system.scheduler.scheduleOnce(duration, self, "wakeUp")
}
def doWork(): Boolean = {
// doing some work, then:
calculateCondition
}
}
Note: I have not tested this code! Should give you some ideas to work with, though.
Upvotes: 8