2017-07-06 112 views
3

如果我在Scala中爲演員定義主管策略,如何使用OneForOneStrategyAllForOneStrategy?有沒有簡單的方法來組合它們,或者我必須定義一個自定義SupervisorStrategy? 下面是一個例子:Akka:如何結合OneForOneStrategy和AllForOneStrategy

class MyActor extends Actor { 
    override val supervisorStrategy = OneForOneStrategy() { 
    case _: NullPointerException => Restart 
    case _: FileNotFoundException => Restart // here I want to restart all children 
    case _: Exception    => Escalate 
    } 
} 

如果我有寫我自己的上司的策略,我該怎麼辦呢?我沒有找到這方面的例子。

回答

0

您將不得不定義自定義主管策略。爲了您的具體使用情況,下面的自定義策略,將工作:

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時,兩個孩子都會重新啓動。

有關自定義策略的幾個注意事項:

  • 它擴展SupervisorStrategy和定義here現有戰略後爲藍本。
  • 它在akka.actor包內部定義爲可以訪問那裏的包 - 私有成員。
  • processFailure,必須在延伸SupervisorStrategy的類中覆蓋的方法之一,在RestartStop上調用,因此對於您的方案,我們在那裏定義自定義行爲。
+0

我很驚訝,它必須在'akk.actor'裏面定義。爲了使它更通用一個也可以重寫OneForOneStartegy並添加一個'RestartAll'和一個'StopAll'決策指令,對吧? – Jojo

+0

應該避免重寫'OneForOneStrategy',因爲它是一個case類。擴展'Decider'類型也是不可能的,因爲它是封閉的,規範('Resume','Restart',...)是大小寫對象(所以我也不能擴展'Restart'來創建'RestartAll') 。爲了使示例更一般化,有必要編寫一個完整的新SupervisorStrategy類。 – Jojo