您將不得不定義自定義主管策略。爲了您的具體使用情況,下面的自定義策略,將工作:
package akka.actor
import java.io.FileNotFoundException
import scala.concurrent.duration._
case class CustomStrategy(
maxNrOfRetries: Int = -1,
withinTimeRange: Duration = Duration.Inf,
override val loggingEnabled: Boolean = true)(val decider: SupervisorStrategy.Decider)
extends SupervisorStrategy {
import SupervisorStrategy._
private val retriesWindow = (maxNrOfRetriesOption(maxNrOfRetries), withinTimeRangeOption(withinTimeRange).map(_.toMillis.toInt))
def handleChildTerminated(context: ActorContext, child: ActorRef, children: Iterable[ActorRef]): Unit =()
def processFailure(context: ActorContext, restart: Boolean, child: ActorRef, cause: Throwable, stats: ChildRestartStats, children: Iterable[ChildRestartStats]): Unit = {
if (cause.isInstanceOf[FileNotFoundException]) {
// behave like AllForOneStrategy
if (children.nonEmpty) {
if (restart && children.forall(_.requestRestartPermission(retriesWindow)))
children foreach (crs ⇒ restartChild(crs.child, cause, suspendFirst = (crs.child != child)))
else
for (c ← children) context.stop(c.child)
}
} else {
// behave like OneForOneStrategy
if (restart && stats.requestRestartPermission(retriesWindow))
restartChild(child, cause, suspendFirst = false)
else
context.stop(child)
}
}
}
Here是測試上述戰略的一個要點。規範會創建一個使用CustomStrategy
的主管,並創建兩個子項。當一個孩子拋出NullPointerException
時,只有該孩子重新啓動;當孩子拋出FileNotFoundException
時,兩個孩子都會重新啓動。
有關自定義策略的幾個注意事項:
我很驚訝,它必須在'akk.actor'裏面定義。爲了使它更通用一個也可以重寫OneForOneStartegy並添加一個'RestartAll'和一個'StopAll'決策指令,對吧? – Jojo
應該避免重寫'OneForOneStrategy',因爲它是一個case類。擴展'Decider'類型也是不可能的,因爲它是封閉的,規範('Resume','Restart',...)是大小寫對象(所以我也不能擴展'Restart'來創建'RestartAll') 。爲了使示例更一般化,有必要編寫一個完整的新SupervisorStrategy類。 – Jojo