Implementacja long ankiet w Scali I play 2.0 z akkÄ…

Wdrażam long ankiet w Play 2.0 w środowisku rozproszonym. Jak rozumiem to jest to, że gdy Play dostaje żądanie, powinien zawiesić w oczekiwaniu na powiadomienie o aktualizacji, a następnie przejść do db, aby pobrać nowe dane i powtórzyć. Zacząłem przyglądać się przykładowi czatu, który oferuje Play 2.0, ale jest w websocket. Co więcej, nie wygląda na to, że może być rozpowszechniany. Więc pomyślałem, że skorzystam z autobusu imprezowego Akki. Wziąłem implementację eventstream i odtworzyłem mój własne z LookupClassification. Jednak jestem zaskoczony, jak mam dostać wiadomość z powrotem (lub w tym przypadku, co powinno być abonent zamiast ActorRef)?

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

Author: Mortimer, 2012-04-10

2 answers

Nie jestem pewien, czy tego szukasz, ale jest dość proste rozwiązanie w próbce zegara komety, które można dostosować do użycia aktorów AKKA. Używa nieskończonego iframe zamiast długiego sondażu. Użyłem zaadaptowanej wersji dla bardziej złożonej aplikacji wykonującej wiele wywołań DB i długie obliczenia w Akce i działa dobrze.

  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"))
  }

Zauważ, że ten fromCallback nie pozwala na łączenie enumeratorów z "andThen" , jest w wersji trunk play2 a metoda generateM, która może być bardziej odpowiednia, jeśli chcesz używać kombinacji.

Nie jest to długa ankieta, ale działa dobrze.
 5
Author: Mortimer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-18 06:47:54

NatknÄ…Å‚em siÄ™ na twoje pytanie, szukajÄ…c tego samego.

Rozwiązanie streamingu okazało się niezadowalające, ponieważ spowodowało "spinner of death" w przeglądarce webkit (tzn. pokazuje, że cały czas się ładuje)

W każdym razie, nie miałem szczęścia znaleźć dobrych przykładów, ale udało mi się stworzyć własny proof-of-concept za pomocą obietnic: https://github.com/kallebertell/longpoll

 1
Author: kerebus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-13 20:11:53