2014-06-13 7 views
7

Possiedo un attore e su alcuni messaggi eseguo un metodo che restituisce Future.Contesto di esecuzione per futures negli attori

def receive: Receive = { 

    case SimpleMessge() => 
     val futData:Future[Int] = ... 
     futData.map { data => 
      ... 
     } 
} 

È possibile passare il contesto effettivo in attesa di questi dati? O Await è il meglio che posso fare se ho bisogno di questi dati in SimpleMessage?

+0

Che cosa stai cercando di fare con i dati provenienti dal futuro? – cmbaxter

+0

Questi sono dati dal mio db (mongo), e voglio filtrarli e solo una parte di essi può essere salvata in un'altra raccolta. Ma fondamentalmente si tratta di dati DB, non posso farlo in background, e devo aspettare per finire questa azione prima del prossimo * SimpleMessage *. –

+0

Si sta inviando un messaggio al 'mittente' o no? –

risposta

10

Se avete veramente bisogno di aspettare il futuro per completare prima di elaborare il messaggio successivo, si può provare qualcosa di simile:

object SimpleMessageHandler{ 
    case class SimpleMessage() 
    case class FinishSimpleMessage(i:Int) 
} 

class SimpleMessageHandler extends Actor with Stash{ 
    import SimpleMessageHandler._ 
    import context._ 
    import akka.pattern.pipe 

    def receive = waitingForMessage 
    def waitingForMessage: Receive = { 

    case SimpleMessage() => 
     val futData:Future[Int] = ... 
     futData.map(FinishSimpleMessage(_)) pipeTo self 
     context.become(waitingToFinish(sender)) 
    } 

    def waitingToFinish(originalSender:ActorRef):Receive = { 
    case SimpleMessage() => stash() 

    case FinishSimpleMessage(i) => 
     //Do whatever you need to do to finish here 
     ... 
     unstashAll() 
     context.become(waitingForMessage) 

    case Status.Failure(ex) => 
     //log error here 
     unstashAll() 
     context.become(waitingForMessage)  
    } 
} 

In questo approccio, elaboriamo un SimpleMessage e quindi passare la gestione logica per riporre tutti i successivi SimpleMessage s ricevuti fino a quando non si ottiene un risultato dal futuro. Quando otteniamo un risultato, un fallimento o meno, togliamo tutti gli altri SimpleMessage s che abbiamo ricevuto mentre aspettiamo il futuro e andiamo sulla nostra strada allegra.

Questo attore attiva e disattiva alternativamente due stati e ciò consente di elaborare completamente uno solo SimpleMessage alla volta senza dover bloccare il futuro.

+2

l'importazione effettiva context.dispatcher funziona – Oleg