2012-04-10 11 views
13

Ich implementiere Long-Polling in Play 2.0 in einer potenziell verteilten Umgebung. Die Art, wie ich es verstehe ist, dass, wenn Play eine Anfrage bekommt, sollte ausstehende Benachrichtigung über ein Update zu suspendieren, dann gehen Sie zu der db um neue Daten zu holen und zu wiederholen. Ich habe angefangen, das Chat-Beispiel anzusehen, das Play 2.0 anbietet, aber es ist im Websocket. Außerdem sieht es nicht so aus, als könnte es verteilt werden. Also dachte ich, ich würde Akkas Eventbus benutzen. Ich nahm die Eventstream-Implementierung und replizierte meine eigene mit LookupClassification. Wie auch immer, ich bin ratlos, wie ich eine Nachricht zurückbekomme (oder, was sollte der Abonnent anstelle von ActorRef sein)?Implementieren lange Polling in Scala und spielen 2.0 mit akka

Event Umsetzung: https://github.com/akka/akka/blob/master/akka-actor/src/main/scala/akka/event/EventStream.scala

Antwort

5

Ich bin nicht sicher, dass ist das, was Sie suchen, aber es ist durchaus eine einfache Lösung im Comet-Uhr Probe, dass Sie AKKA Akteure verwenden anpassen können. Es verwendet einen unendlichen Iframe anstelle eines langen Pollings. Ich habe eine angepasste Version für eine komplexere Anwendung verwendet, die mehrere DB-Aufrufe und lange Berechnungen in AKKA-Darstellern ausführt, und es funktioniert gut.

def enum = Action { 
    //get your actor 
    val myActorRef = Akka.system.actorOf(Props[TestActor]) 

    //do some query to your DB here. Promise.timeout is to simulate a blocking call 
    def getDatabaseItem(id: Int): Promise[String] = { Promise.timeout("test", 10 milliseconds) } 

    //test iterator, you will want something smarter here 
    val items1 = 1 to 10 toIterator 

    // this is a very simple enumerator that takes ints from an existing iterator (for an http request parameters for instance) and do some computations 
    def myEnum(it: Iterator[Int]): Enumerator[String] = Enumerator.fromCallback[String] {() => 
     if (!items1.hasNext) 
     Promise.pure[Option[String]](None) //we are done with our computations 
     else { 

     // get the next int, query the database and compose the promise with a further query to the AKKA actor 
     getDatabaseItem(items1.next).flatMap { dbValue => 
      implicit val timeout = new Timeout(10 milliseconds) 
      val future = (myActorRef ? dbValue) mapTo manifest[String] 

      // here we convert the AKKA actor to the right Promise[Option] output 
      future.map(v => Some(v)).asPromise 
     } 
     } 
    } 

    // finally we stream the result to the infinite iframe. 
    // console.log is the javascript callback, you will want something more interesting. 
    Ok.stream(myEnum(items1) &> Comet(callback = "console.log")) 
    } 

Beachten Sie, dass dieser fromCallback nicht Sie Aufzählungen erlaubt zu kombinieren mit „andthen“ gibt es in der Kofferraum Version von play2 eine generateM Methode, die besser geeignet sein könnte, wenn Sie Kombinationen verwenden mögen.

Es ist nicht lange polling, aber es funktioniert gut.

1

Ich stolperte auf Ihre Frage bei der Suche nach der gleichen Sache.

fand ich die Streaming-Lösung nicht zufriedenstellend, da sie „Spinner des Todes“ in Webkit-Browser verursacht (dh zeigt es die ganze Zeit wird geladen)

Wie auch immer, hatte kein Glück bei der Suche gute Beispiele, aber ich schaffte es Erstellen Sie meinen eigenen Proof-of-Concept mit Versprechungen: https://github.com/kallebertell/longpoll