Подтвердить что ты не робот

Выполнение длинных опросов в scala и воспроизведение 2.0 с помощью akka

Я выполняю длительный опрос в Play 2.0 в потенциально распределенной среде. Я понимаю, что когда Play получает запрос, он должен приостановить ожидающее уведомление об обновлении, а затем перейти к db для получения новых данных и повторения. Я начал смотреть пример чата, который предлагает Play 2.0, но он находится в websocket. Кроме того, он не похож на способ его распространения. Поэтому я думал, что буду использовать автобус событий Akka. Я принял реализацию потока событий и реплицировал свою собственную с помощью LookupClassification. Однако я в тупике о том, как я получу сообщение (или, если на то пошло, какой должен быть абонент вместо ActorRef)?

Реализация EventStream: https://github.com/akka/akka/blob/master/akka-actor/src/main/scala/akka/event/EventStream.scala

4b9b3361

Ответ 1

Я не уверен, что это то, что вы ищете, но в образце комет-часов есть довольно простое решение, которое вы можете адаптировать для использования актеров AKKA. Он использует бесконечный iframe вместо длительного опроса. Я использовал адаптированную версию для более сложного приложения, выполняющего несколько вызовов БД и длинных вычислений в актерах AKKA, и он отлично работает.

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

Обратите внимание, что это из Callback не позволяет объединять счетчики с "andThen", в версии trunk2 для play2 используется метод generateM, который может быть более уместным, если вы хотите использовать комбинации.

Это не длинный опрос, но он отлично работает.

Ответ 2

Я наткнулся на ваш вопрос, ища то же самое.

Я обнаружил, что потоковое решение неудовлетворительно, поскольку они вызвали "счетчик смерти" в браузере webkit (т.е. показывает, что он загружается все время)

Во всяком случае, не было удачи найти хорошие примеры, но мне удалось создать свою собственную концепцию-концепцию с помощью promises: https://github.com/kallebertell/longpoll