2014-10-11 11 views
5

Po użyciu Play! Ramy na chwilę spoglądam na Spray. Zacząłem od próbki, którą znalazłem na GitHub, teraz chcę ją zmodyfikować, ale nie jest mi łatwo zrozumieć, jak to działa.Wywołanie aktora na trasie natrysku i oczekiwanie na odpowiedź aktora

Jak mogę czekać na wiadomość od aktora w poniższym kodzie?

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

Nie napisałem naszego kodu trasy, więc nie wiem najlepiej, ale zasadniczo nigdy nie czekasz: zamiast tego przekazujesz tę prośbę aktorowi lub aktorowi, który został zawinięty w przyszłości za pomocą polecenia odpowiedzialnego za wysłanie odpowiedzi po zakończeniu przetwarzania. – Rup

+0

Jestem nowy w Sprayu, więc nie mogę uzyskać żadnej korzyści z twojej odpowiedzi. Wolę fragment kodu. – Max

Odpowiedz

12

Spray opiera się już na akka.io

Tak więc, jeśli chcesz, żeby zakończyć swoją trasę z odpowiedzią aktora, można użyć zapytać wzorzec

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] 

Jeśli chcesz przekazać Żądaj od swojego aktora modelu i kompletnej trasy gdzieś w systemie aktorskim, musisz przekazać RequestContext do aktorów. Być może ten example może ci pomóc. Powodzenia!

+0

Dzięki! Możesz dodać "import scala.concurrent.Future", ponieważ również Java ma przyszłość. I "importuj akka.actor.Actor" tylko dlatego, że jest również potrzebny. – akauppi

+0

Jedna ważna uwaga: osoba już używa aktorów (patrz "klasyfikator: ActorRef" w q). Jeśli ktoś szuka sposobu na logikę wielowątkowych odpowiedzi, to właśnie do Future [HttpResponse] należy iść, a nie aktorzy. Zobacz https://www.chrisstucchio.com/blog/2013/actors_vs_futures.html – akauppi

3

Spójrz na mój przykładowy projekt. This service używa kontraktów Futures do uzupełniania tras. Jak komentował Rup, zła praktyka czeka na odpowiedź. Oddaj natychmiast przyszłość i pozwól jej zakończyć, gdy uzyska wynik.

W twoim przykładzie classifier ! cm używa wzoru aktora "tell". Wysyła wiadomość cm do aktora classifier i przechodzi dalej. Jeśli chcesz oczekiwać odpowiedzi w przyszłości, użyj wzoru "ask": classifier ? cm. W twojej metodzie otrzymywania aktora cm będziesz zwracał przyszłość z sender ! responseMsg, która powróci w przyszłości.

Powiązane problemy