2012-01-01 20:48:03 +01:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
|
|
|
|
*/
|
|
|
|
|
package akka
|
|
|
|
|
|
|
|
|
|
import akka.actor.Actor
|
|
|
|
|
import akka.actor.ActorRef
|
|
|
|
|
import akka.actor.ActorSystem
|
|
|
|
|
import akka.actor.ActorTimeoutException
|
|
|
|
|
import akka.actor.PoisonPill
|
|
|
|
|
import akka.actor.Props
|
|
|
|
|
import akka.actor.ReceiveTimeout
|
|
|
|
|
import akka.actor.Terminated
|
|
|
|
|
import akka.dispatch.Future
|
|
|
|
|
import akka.dispatch.Promise
|
|
|
|
|
import akka.util.Duration
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Akka patterns that provide solutions to commonly occurring problems.
|
|
|
|
|
*/
|
|
|
|
|
package object pattern {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a [[akka.dispatch.Future]] that will be completed with `Right` `true` when
|
|
|
|
|
* existing messages of the target actor has been processed and the actor has been
|
|
|
|
|
* terminated.
|
|
|
|
|
*
|
|
|
|
|
* Useful when you need to wait for termination or compose ordered termination of several actors.
|
|
|
|
|
*
|
|
|
|
|
* If the target actor isn't terminated within the timeout the [[akka.dispatch.Future]]
|
|
|
|
|
* is completed with `Left` [[akka.actor.ActorTimeoutException]].
|
|
|
|
|
*/
|
|
|
|
|
def gracefulStop(target: ActorRef, timeout: Duration)(implicit system: ActorSystem): Future[Boolean] = {
|
|
|
|
|
if (target.isTerminated) {
|
2012-01-01 21:27:52 +01:00
|
|
|
Promise.successful(true)
|
2012-01-01 20:48:03 +01:00
|
|
|
} else {
|
2012-01-01 21:27:52 +01:00
|
|
|
val result = Promise[Boolean]()
|
2012-01-01 20:48:03 +01:00
|
|
|
system.actorOf(Props(new Actor {
|
|
|
|
|
// Terminated will be received when target has been stopped
|
|
|
|
|
context watch target
|
|
|
|
|
target ! PoisonPill
|
|
|
|
|
// ReceiveTimeout will be received if nothing else is received within the timeout
|
|
|
|
|
context setReceiveTimeout timeout
|
|
|
|
|
|
|
|
|
|
def receive = {
|
2012-01-01 21:27:52 +01:00
|
|
|
case Terminated(a) if a == target ⇒
|
|
|
|
|
result success true
|
2012-01-01 21:30:04 +01:00
|
|
|
context stop self
|
2012-01-01 20:48:03 +01:00
|
|
|
case ReceiveTimeout ⇒
|
2012-01-01 21:27:52 +01:00
|
|
|
result failure new ActorTimeoutException(
|
|
|
|
|
"Failed to stop [%s] within [%s]".format(target.path, context.receiveTimeout))
|
2012-01-01 21:30:04 +01:00
|
|
|
context stop self
|
2012-01-01 20:48:03 +01:00
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|