2016-11-10 2 views
1

J'utilise Akka et voudrais exécuter du code pour tous les cas d'une fonction partielle. Pour la supervision des acteurs, j'ai quelque chose comme:Scala, code par défaut pour la fonction partielle?

val supervisorStrategy = OneForOneStrategy() { 
    case npe: NullPointerException => Stop 
    case re: RuntimeException => Restart 
} 

La seule façon que j'ai trouvé d'exécuter un code pour tous les cas sans avoir à écrire de nouveau à tous les cas, est la suivante:

val pf = new PartialFunction[Throwable, Directive] { 
    def apply(throwable: Throwable) = { 
    doSomething(throwable) 
    throwable match { 
     case NullPointerException => Stop 
     case RuntimeException => Restart 
    } 
    } 

    def isDefinedAt(throwable: Throwable) = true 
} 

val supervisorStrategy = OneForOneStrategy()(pf) 

Je regardé autour et à d'autres réponses (comme this one) mais n'a pas pu trouver une alternative à celle que je suis venu avec.

+0

Voulez-vous que 'doSomething' soit appelé même si une exception qui n'est ni 'NullPointerException' ni' RuntimeException' est passée? –

Répondre

0

Merci pour les autres réponses, mais dans cette situation particulière AKKA je ne peux pas les amener à travailler. Par exemple, ce ne sera pas compilé:

val ft = OneForOneStrategy() { x: Throwable => 
    doSomething(x) 
    x match { 
    case npe: NullPointerException => Stop 
    case re: RuntimeException => Stop 
    } 
} 

Error:(48, 47) type mismatch; 
found : Throwable => akka.actor.SupervisorStrategy.Directive 
required: akka.actor.SupervisorStrategy.Decider (which expands to) PartialFunction[Throwable,akka.actor.SupervisorStrategy.Directive] 

J'utilise Akka 2.4.11, et Scala 2.11.8

La seule solution de travail a été pour moi la façon dont je l'ai décrit dans la question initiale.

1

Cela devrait le faire:

val supervisorStrategy = OneForOneStrategy() { 
case x => 
    doSomething(x) 
    x match { 
    case npe: NullPointerException => Stop 
    case re: RuntimeException => Restart 
    } 
} 
+0

Je l'avais essayé mais il ne compile pas: "Type de paramètre manquant: x" – ticofab

+0

il semble fonctionner si je spécifie à la fois le type de x et la signature de fonction réelle: def pf3: PartialFunction [Throwable, Directive] et (x : Throwable) – ticofab

+0

pour une raison étrange, cela ne fonctionne pas :( – ticofab

1

ne semble pas spécifique Akka. Vous pouvez toujours combiner deux fonctions en utilisant andThen. Plus précisément:

package com.example 

import akka.actor.OneForOneStrategy 
import akka.actor.SupervisorStrategy.{Decider, Restart, Stop} 

object Answer extends App { 
    val doSomething:PartialFunction[Throwable, Throwable] = { case e => 
    println(s"doing something with $e") 
    e 
    } 

    val decide:Decider = { 
    case _:NullPointerException => Stop 
    case _:RuntimeException => Restart 
    } 

    val strategy = OneForOneStrategy()(doSomething andThen decide) 

    val errors = Seq(new NullPointerException, new RuntimeException) 
    errors map strategy.decider foreach println 
} 

Plus généralement:

package com.example 

object Answer extends App { 
    val inspect:PartialFunction[Throwable, Throwable] = { case e => 
     println(s"inspecting $e") 
     e 
    } 

    val decide:PartialFunction[Throwable, String] = { 
    case npe:NullPointerException => "NPE!" 
    case iae:IllegalArgumentException => "Bad arg!" 
    } 

    val combined = inspect andThen decide 

    val errors = Seq(new NullPointerException, new IllegalArgumentException) 
    errors map combined foreach println 
}