2017-08-08 1 views
0

J'aimerais qu'un acteur envoie un message au démarrage et reçoive une réponse plus tard.Envoi d'un message sur le démarrage d'un acteur avec un émetteur réel (non temporaire) ActorRef?

L'envoi du message depuis preStart génère une référence temporaire sender (car l'acteur n'a pas encore démarré?). Donc, la réponse sera probablement une lettre morte.

Des conseils seraient appréciés. Excuses si ma prémisse est mal informé - je suis nouveau à Akka.

+0

Vous pouvez envoyer un message initial à votre acteur, qui déclenchera l'envoi du message de démarrage. Alternativement, faites de votre acteur un étatful; son état de démarrage enverrait le message et ensuite il passerait à l'état opérationnel, où il s'attendrait à recevoir la réponse. –

+0

Merci @BobDalgleish - est-ce que cela implique un appel 'get (receive)' dans 'preStart'? –

Répondre

2

Une approche est d'envoyer un message à self à preStart:

class MyActor extends Actor { 

    def preStart(): Unit = { 
    self ! CallService 
    } 

    def receive = { 
    case CallService => 
     (service ? ServiceRequest).mapTo[ServiceResponse].pipeTo(self) 
    case ServiceResponse => 
     // do something with the response 
    } 
} 

Comme décrit dans ce answer, si vous voulez que l'acteur pour envoyer le message avant qu'il traite tous les autres messages, vous pourriez stash les autres messages:

class MyActor extends Actor with Stash { 

    def preStart(): Unit = { 
    self ! CallService 
    } 

    def uninitialized: Receive = { 
    case CallService => 
     (service ? ServiceRequest).mapTo[ServiceResponse].pipeTo(self) 
     unstashAll() 
     context.become(initialized) 
    case _ => stash() // if we get a message other than CallService, stash it 
    } 

    def initialized: Receive = { 
    case ServiceResponse => 
     // do something with the response from the service 
    case ... 
    } 

    def receive = uninitialized 
} 
1

Votre prémisse est en effet pas correct: quand prédémarrage fonctionne l'acteur est déjà complètement démarré, il est self référence n'est jamais temporaire. Sans code, il est impossible de vous aider plus loin, cependant.

0

L'expéditeur doit toujours être considéré comme "temporaire" - cf. ce billet de blog, par exemple:

La règle est tout simplement refermera jamais sur la méthode de l'expéditeur dans un bloc de code qui est potentiellement exécuté dans un autre thread, comme une tâche planifiée ou un avenir. L'astuce consiste à capturer l'expéditeur actuel dans un val, comme illustré ci-dessous ...

- Closing Over An Akka Actor Sender In The Receive

Faites une copie de l'expéditeur, puis plus tard, lorsque vous êtes prêt à répondre, répondre à cette copie de l'acteurRef et non pas "expéditeur".