Избегайте.await в запросе astic4s

В документации astic4s по классу типов HitReader говорится, что .await следует избегать в производстве:

case class Character(name: String, location: String)

implicit object CharacterHitReader extends HitReader[Character] {
  override def read(hit: Hit): Either[Throwable, Character] = {
    Right(Character(hit.sourceAsMap("name").toString, hit.sourceAsMap("location").toString))
  }
}

val resp = client.execute {
  search("gameofthrones" / "characters").query("kings landing")
}.await // don't block in real code

// .to[Character] will look for an implicit HitReader[Character] in scope
// and then convert all the hits into Characters for us.
val characters :Seq[Character] = resp.to[Character]

Я хотел бы взять возвращенный characters значение и использовать его для генерации ответа в моем веб-приложении (например, это может быть JSON).

Конечно, если.await просто удаляется, он генерирует ошибку, которую ожидал Future:

Constructor cannot be instantiated to expected type;
[error]  found   : scala.util.Left[A,B]
[error]  required: scala.concurrent.Future[Either[com.sksamuel.elastic4s.http.RequestFailure,com.sksamuel.elastic4s.http.RequestSuccess[com.sksamuel.elastic4s.http.search.SearchResponse]]]

Так что так хорошо, и я понимаю, что мне придется ждать дальнейшей обработки, пока Elasticsearch не вернет результат. Тем не менее, таким образом поток блокируется, и при высокой нагрузке JWM падает из-за тайм-аутов. Я хотел бы освободить эти ресурсы, пока Elasicsearch работает над запросом.

Как, вообще, возвращенные значения запроса могут быть обработаны в дальнейшем неблокирующим образом?

А конкретно, как можно .await быть удален и неблокирующий вызов создан для сервера?

1 ответ

Я не использую упругости. Но если вы используете его вместе с Play, у вас все хорошо.

Просто сопоставьте будущее с тем, что вам нравится. Взяв пример отсюда play -astic4s:

class BookDao @Inject()(
    cs: ClusterSetup,
    elasticFactory: PlayElasticFactory,
    @Named("book") indexAndType: IndexAndType) extends
        ElasticDsl {

    private[this] lazy val client = elasticFactory(cs)

    def searchByAnything(q: String): Future[RichSearchResponse] = client execute {
        search in indexAndType query q
    }
}

Вы можете использовать это в своем контроллере:

class HomeController @Inject()(dao: BookDao, myExecutionContext: MyExecutionContext, val controllerComponents: ControllerComponents) extends BaseController {
  def index = Action.async {
    dao.searchByAnything("your_search")
      .map( Ok(YourJsonEncoder.toJson))
    }(myExecutionContext)
  }
}
Другие вопросы по тегам