1

I'm using Elastic4s (Scala Client for ElasticSearch).

I can retrieve multiGet results with await :

val client = HttpClient(ElasticsearchClientUri(esHosts, esPort))
val resp = client.execute {
  multiget(
    get(C1) from "mlphi_crm_0/profiles" fetchSourceInclude("crm_events"),
    get(C2) from "mlphi_crm_0/profiles" fetchSourceInclude("crm_events"),
    get(C3) from "mlphi_crm_0/profiles" fetchSourceInclude("crm_events")
  )
}.await
val result = resp.items

But I've read that in practice it's better to avoid this ".await". How can we do that ? thanks

2 Answers2

1

You shouldn't use .await because you're blocking the thread waiting for the future to return.

Instead you should handle the future like you would any other API that returns futures - whether that be reactive-mongo, akka.ask or whatever.

sksamuel
  • 16,154
  • 8
  • 60
  • 108
0

I realise this is old, but in case anyone else comes across it, the simplest way to handle this would be:

val client = HttpClient(ElasticsearchClientUri(esHosts, esPort))
val respFuture = client.execute {
  multiget(
    get(C1) from "mlphi_crm_0/profiles" fetchSourceInclude("crm_events"),
    get(C2) from "mlphi_crm_0/profiles" fetchSourceInclude("crm_events"),
    get(C3) from "mlphi_crm_0/profiles" fetchSourceInclude("crm_events")
  )
}

respFuture.map(resp=> ...[do stuff with resp.items])

The key thing here is that your processing actually takes place in a subthread, which Scala takes care of calling for you when, any only when, the data is ready for you. The caller keeps running immediately after respFuture.map(). Whatever your function in map(()=>{}) returns is passed back as a new Future; if you don't need it then use onComplete or andThen as they make error handling a little easier.

See https://docs.scala-lang.org/overviews/core/futures.html for more details on Futures handling, and https://alvinalexander.com/scala/concurrency-with-scala-futures-tutorials-examples for some good examples

fredex42
  • 90
  • 7