2014-10-11 7 views
5

Dopo aver utilizzato Play! Quadro per un po ', sto dando un primo sguardo a Spray. Ho iniziato da un campione che ho trovato su GitHub, ora voglio modificarlo ma non è facile per me capire come funziona.Chiamare un attore in un percorso Spray e attendere la risposta dell'attore

Come posso attendere un messaggio da un attore nel codice qui sotto?

package api 

import akka.actor.ActorRef 
import scala.concurrent.ExecutionContext 
import spray.routing.Directives 
import core.ClassifierActor 

class ClassifierService(classifier: ActorRef)(implicit executionContext: ExecutionContext) 
    extends Directives with DefaultJsonFormats { 

    import ClassifierActor._ 

    implicit val classifyMessageFormat = jsonFormat4(ClassifyMessage) 

    val route = 
    path("classify") { 
     post { 
     handleWith { 
      // The ClassifierActor gets a ClassifyMessage and 
      // sends a ClassifiedMessage back to the sender. 
      // How can wait for the ClassifiedMessage here 
      // and send a HttpResponse back? 
      cm: ClassifyMessage => classifier ! cm 
      // ??? 
     } 
     } 
    } 

} 
+0

Non ho scritto il nostro codice di instradamento quindi non conosco il modo migliore ma in generale non si aspetta mai: invece si passa la richiesta ad un attore o forse ad un attore avvolto in un futuro tramite un tell che è responsabile per inviare la risposta una volta completata l'elaborazione. – Rup

+0

Sono nuovo di Spray, quindi non posso trarre alcun vantaggio dalla tua risposta. Avrei bisogno di un frammento di codice. – Max

risposta

12

Spray si basa già su akka.io

Quindi, se si desidera solo per completare il percorso con la risposta attore, è possibile utilizzare chiedere modello

import akka.pattern.ask 
import scala.concurrent.duration._ 
implicit val timeout = Timeout(5 seconds) // needed for `?` below 

val route = 
    path("classify") { 
     post { 
     onComplete(actorResponse(yourActor, yourMessage)) { 
      complete(_) 
     } 
     } 
    } 

def actorResponse[T](actor: ActorRef, msg: ClassifyMessage): Future[T] = 
(actor ? msg).mapTo[T] 

Se si desidera inoltrare richiede al tuo modello di attore e completare la rotta da qualche parte nel sistema degli attori, devi inoltrare RequestContext agli attori. Forse, questo example potrebbe aiutarti. In bocca al lupo!

+0

Grazie! È possibile aggiungere "import scala.concurrent.Future" poiché anche Java ha un futuro. E 'importare akka.actor.Actor' solo perché è anche necessario. – akauppi

+0

Una nota importante: la persona sta già usando gli attori (vedere il "classificatore: ActorRef" nella q). Se si sta semplicemente cercando un modo per la logica di risposta multithread, Future [HttpResponse] è la strada da percorrere, non gli attori. Vedi https://www.chrisstucchio.com/blog/2013/actors_vs_futures.html – akauppi

3

Dai un'occhiata al mio esempio di progetto. This service utilizza Futures per completare le rotte. Come ha commentato Rup, è una cattiva pratica aspettare una risposta. Restituisci un futuro immediatamente e fallo completare quando ottiene un risultato.

Nell'esempio classifier ! cm si utilizza il pattern "tell" dell'attore. Invia un messaggio cm all'attore classifier e si sposta su. Se vuoi aspettarti una risposta in futuro usa il modello "chiedi": classifier ? cm. Nel tuo metodo di ricezione dell'attore cm restituirai un futuro con sender ! responseMsg che tornerà in futuro.