避免使用elastic4s查询中的.await

时间:2018-04-10 11:09:34

标签: scala playframework elastic4s

在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并为服务器创建非阻塞调用?

1 个答案:

答案 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)
  }
}