Асинхронный контроллер Play Framework блокирует последующие вызовы для того же контроллера - PullRequest
0 голосов
/ 01 ноября 2018

Моя цель - выполнить несколько запросов к базе данных с асинхронного контроллера, а затем вернуть ответ.

Я играю с примером проекта, сейчас просто имитирую запросы к БД с помощью сна, но я заметил, что, что бы я ни делал, интерфейс REST даже не запускает сон второго запроса до тех пор, пока первый один заканчивает. Например: если я вызываю интерфейс REST из одной вкладки в браузере, а затем через 1 секунду снова из другой вкладки, я ожидаю, что вторая тоже получит ответ через 10 секунд, но на самом деле это 19.

Также, похоже, он не использует пул "database-io":

1: application-akka.actor.default-dispatcher-2

2: application-akka.actor.default-dispatcher-5

Мой код:

@Singleton
class AsyncController @Inject()(cc: ControllerComponents, actorSystem: ActorSystem) extends AbstractController(cc) {

  implicit val executionContext = actorSystem.dispatchers.lookup("database-io")

  def message = Action.async {
    getFutureMessage().map { msg => Ok(msg) }
  }

  private def getFutureMessage(): Future[String] = {
    val defaultThreadPool = Thread.currentThread().getName;
    println(s"""1: $defaultThreadPool""")

    val promise: Promise[String] = Promise[String]()
    actorSystem.scheduler.scheduleOnce(0 second) {
      val blockingPool = Thread.currentThread().getName;
      println(s"""2: $blockingPool""")

      Thread.sleep(10000)
      promise.success("Hi!")
    }(actorSystem.dispatcher)
    promise.future
  }

}

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

Вам необходимо избегать блокировки кода. В основном:

  1. Вы можете метод, который возвращает будущее.

  2. Вы наносите на нее карту.

  3. Вы восстанавливаете любой сбой, который может принести результат Future.

Допустим, у меня есть:

def userAge (userId: String): Future[Int] = ???

Затем вы отображаете в него:

userAge.map{
  age => ??? //everything is ok
}.recover{ case e: Throwable => ??? //Do something when it fails 

Обратите внимание, что если у вас более одного звонка, другой map становится flatMap, потому что вы хотите Future[...] что-то, а не Future[Future[...]].

0 голосов
/ 05 ноября 2018

Причин такого поведения может быть две:

  1. Вы используете режим разработки (1 поток), или конфигурация вашего продукта настроена только для одного потока.
  2. Браузер блокирует второй запрос до получения ответа от первого. Эта фраза: «Если я вызываю интерфейс REST из одной вкладки в браузере». Попробуйте сделать то же самое из разных браузеров.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...