scala - Akka: testing monitoring\death watch -
scala - Akka: testing monitoring\death watch -
in scenario have 2 actors:
watchee (i utilize testprobe) watcher (watcher wrapped testactorref expose internal state track in test) watcher should take actions when watchee dies.
here finish test case i've written far:
class temptest(_system: actorsystem) extends testkit(_system) implicitsender funsuitelike matchers beforeandafterall { def this() = this(actorsystem("temptest")) override def afterall { testkit.shutdownactorsystem(system) } class watcheractor(watchee: actorref) extends actor { var state = "initial" context.watch(watchee) override def receive: receive = { case "start" => state = "start" case _: terminated => state = "terminated" } } test("example") { val watchee = testprobe() val watcher = testactorref[watcheractor](props(new watcheractor(watchee.ref))) assert(watcher.underlyingactor.state === "initial") watcher ! "start" // "start" sent , handled watcher synchronously assert(watcher.underlyingactor.state === "start") system.stop(watchee.ref) // cause terminated sent , handled asynchronously watcher thread.sleep(100) // best way avoid blocking here? assert(watcher.underlyingactor.state === "terminated") } } now, since involved actors utilize callingthreaddispatcher (all akka's test helpers gets constructed using props .withdispatcher(callingthreaddispatcher.id)) can safely assume when statement returns:
watcher ! "start" ... "start" message processed watchingactor , can create assertions based in watcher.underlyingactor.state
however, based on observations, when stop watchee using system.stop or sending kill terminated message produced side effect of watchee death gets executed asynchronously, in thread.
not-a-solution stop watchee, block thread time , verify watcher state after that, i'd know how right way (i.e. how sure after killing actor it's watcher received , processed terminated message signaling it's death)?
edit: after give-and-take , testing op, have found out sending poisonpill mean of terminating watched actor achieves desired behavior, terminated ppill processed synchronously while stop or kill processed asynchronously.
while not sure reason, our best bet due fact killing actor raises exception while ppilling not.
apparently, has nil using gracefulstop pattern per original suggestion, i'll leave reported below.
in summary, solution op's problem terminate watched actor sending ppill instead kill message or doing system.stop.
old reply begins here:
i may going suggest bit unrelated, sense may apply.
if understood correctly want terminate actor synchronously, i.e. returns 1 time actor officially death , death has been recorded (in case watcher).
in general, death notification, else in akka, async. nonetheless, it's possible obtain synchronous death confirmation using gracefulstop pattern (akka.pattern.gracefulstop).
to so, code should similar to:
val timeout = 5.seconds val killresultfuture = gracefulstop(victimref, timeout, poisonpill) await.result(killresultfuture, timeout) what sending poisonpill victim (note: can utilize custom message), reply future completed 1 time victim dies. using await.result guaranteed synchronous.
unfortunately, usable if a) actively killing victim , don't instead want respond external cause of death b) can utilize timeouts , blocking in code. maybe can adapt pattern situation.
scala testing akka akka-testkit akka-monitoring
Comments
Post a Comment