Избегайте.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)
}
}