2014-10-11 7 views
5

Nachher haben Play verwendet! Framework für eine Weile, ich sehe einen ersten Blick auf Spray. Ich habe mit einem Sample begonnen, das ich auf GitHub gefunden habe, jetzt möchte ich es modifizieren, aber es ist nicht einfach für mich zu verstehen, wie es funktioniert.Einen Schauspieler in einer Spray-Route anrufen und auf die Antwort des Actors warten

Wie kann ich auf eine Nachricht von einem Actor im folgenden Code warten?

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

Ich habe unseren Routingcode nicht geschrieben, also weiß ich nicht den besten Weg, aber im Großen und Ganzen wartest du nie: Stattdessen übergibst du die Anfrage an einen Schauspieler oder einen Schauspieler, der in Zukunft über einen Tell, der dafür verantwortlich ist, ist Senden der Antwort, sobald die Verarbeitung abgeschlossen ist. – Rup

+0

Ich bin neu in Spray, also kann ich keinen Vorteil aus Ihrer Antwort bekommen. Ich brauche lieber einen Code-Schnipsel. – Max

Antwort

12

Spray basiert bereits auf akka.io

Wenn Sie also wollen einfach nur Ihre Route mit dem Schauspieler Reaktion zu vervollständigen, können Sie Muster

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] 

fragen verwenden Wenn Sie weiterleiten möchten Anforderung an Ihr Akteursmodell und vollständige Route irgendwo im Akteursystem, Sie müssen RequestContext an Akteure weiterleiten. Vielleicht könnte diese example Ihnen helfen. Viel Glück!

+0

Danke! Sie könnten 'import scala.concurrent.Future' hinzufügen, da auch Java eine Zukunft hat. Und 'importieren akka.actor.Actor' nur weil es auch benötigt wird. – akauppi

+0

Eine wichtige Anmerkung: Die Person benutzt bereits Schauspieler (siehe "Klassifikator: ActorRef" in der q). Wenn man einfach nach einem Weg zur Multithread-Antwortlogik sucht, ist Future [HttpResponse] der richtige Weg, nicht Schauspieler. Siehe https://www.chrisstucchio.com/blog/2013/actors_vs_futures.html – akauppi

3

Schauen Sie sich mein Beispielprojekt an. This service verwendet Futures, um Routen zu vervollständigen. Wie Rup bemerkte, ist es eine schlechte Übung, auf eine Antwort zu warten. Geben Sie eine Zukunft sofort zurück und lassen Sie sie abgeschlossen, wenn ein Ergebnis erzielt wird.

In Ihrem Beispiel verwendet classifier ! cm den Schauspieler "Tell" -Muster. Er sendet eine Nachricht cm an den classifier Aktor und geht weiter. Wenn Sie möchten, dass es in Zukunft eine Antwort erwartet, verwenden Sie das "ask" -Muster: classifier ? cm. In Ihrer cm Aktion erhalten Sie eine Zukunft mit sender ! responseMsg, die in Zukunft zurückgegeben wird.