pekko/akka-actor/src/main/scala/akka/pattern/package.scala

60 lines
1.9 KiB
Scala
Raw Normal View History

/**
* 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) {
Promise.successful(true)(system.dispatcher)
} else {
val result = Promise[Boolean]()(system.dispatcher)
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 = {
case Terminated(a)
result.complete(Right(true))
system.stop(self)
case ReceiveTimeout
result.complete(Left(
new ActorTimeoutException("Failed to stop [%s] within [%s]".format(target.path, context.receiveTimeout))))
system.stop(self)
}
}))
result
}
}
}