2017-08-16 1 views
0

J'ai deux acteurs A et B. Un contrôleur envoie une requête à l'acteur A. Maintenant, l'acteur A renvoie une réponse de type Try[AbcResponse]. AbcResponse étant une classe de cas ici. Acteur A basé sur une certaine logique pourrait renvoyer directement cette réponse ou il pourrait conditionnellement appeler un autre acteur B en utilisant demander. Après avoir manipulé la réponse de B, il envoie alors la réponse de type Try[AbcResponse] au contrôleur.Scala: Acteur conditionnel Chaining

Alors que dois-je faire dans mon acteur A pour gérer cette situation. Je ne veux pas mettre d'attente dans mon acteur A parce que cela gâcherait le pool de threads et provoquerait des ralentissements dans le système. Comment puis-je gérer efficacement cela?

Répondre

0

Vous pouvez transmettre la référence de l'expéditeur dans un message à l'acteur B et pipe la réponse de l'acteur B à self. De toute évidence, l'acteur B dans sa réponse aurait à transmettre cette référence de retour à l'acteur A.

import akka.pattern.{ask, pipe} 

case class MsgToActorB(..., target: ActorRef) 
case class ResponseFromActorB(..., target: ActorRef) 

class ActorA extends Actor { 
    def receive = { 
    case r: Request => 
     val s = sender 
     implicit val timeout = Timeout(5 seconds) 
     // do something with the request 
     if (someCondition) 
     s ! Try(AbcResponse(...)) 
     else 
     (actorB ? MsgToActorB(..., s)).mapTo[ResponseFromActorB].pipeTo(self) 

    case ResponseFromActorB(..., target) => 
     // do something with the response from B and send a response to the original sender 
     target ! Try(AbcResponse(...)) 
    } 
} 

Bien que l'approche ci-dessus est sûr, ce serait plus simple de ne pas utiliser ask comme indiqué ci-dessous. Si vous devez utiliser ask et si l'acteur B bloque lorsqu'il traite un message de l'acteur A, pensez à configurer un répartiteur distinct comme décrit here.

def receive = { 
    case r: Request => 
    val s = sender 
    // do something with the request 
    if (someCondition) 
     s ! Try(AbcResponse(...)) 
    else 
     actorB ! MsgToActorB(..., s) 

    case ResponseFromActorB(..., target) => 
    // do something with the response from B and send a response to the original sender 
    target ! Try(AbcResponse(...)) 
} 
+0

Dans cette situation est-il mauvais de mettre un callback dans l'acteur lui-même après avoir appelé l'acteur B en utilisant ask? – Sidhant

+0

@Sidhant: Utiliser 'mapTo' et' pipeTo' (qui ne sont pas des callbacks) avec 'ask' est un modèle courant, comme mentionné [ici] (http://doc.akka.io/docs/akka/2.5.4 /scala/actors.html#ask-send-and-receive-future) et dans d'autres parties de la documentation. – chunjef