在HitReader Typeclass的elastic4s文档中,它说生产中应该避免使用.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
值并使用它在我的Web应用程序中生成响应(例如,这可能是JSON)。
当然,如果简单地删除了.await,则会产生一个预期未来的错误:
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
并为服务器创建非阻塞调用?
答案 0 :(得分:0)
我不是弹性的。但如果你和Play一起使用它就可以了。
只需将Future映射到您喜欢的任何输出。以这里为例play-elastic4s:
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
}
}
您可以在Controller中使用它:
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)
}
}