Home > Net >  Scala async recursion with putting await.result inside Future
Scala async recursion with putting await.result inside Future

Time:10-08

I have this sample code below. I don't want to block inside combinator resource.map, so I put Await.result inside Future. But when I test this async recursion, I get concurrent.TimeoutException from myRes. What is the problem with the code? How do I fix it? Thank you.

// Code start here
val responses = Future.sequence(resource.map(params => asyncRecursionFunc(params)))
Await.result(responses, 5.minutes)

// My async function
def asyncRecursionFunc(params: sampleParameters, maxTryTimes: Int = 2, awaitTime: Int = 1): Future[(Seq[sample], String)] = {
    val res: Future[GraphQLCluent.GraphQLResponse[SearchQueryResponse]] = client.query("gql", params).result
    Future {
        val myRes: GraphQLCluent.GraphQLResponse[SearchQueryResponse] = Await.result(res, 2.minutes)
        val myValue: Seq[sample] = myRes.right.toSeq.flatmap(res => res) 
        if( !myValue.isEmpty || maxTryTimes <= 0 ){
            (myValue, "stringMessage")
        }
        else{
            Await.result(asyncRecursionFunc(params, maxTryTimes - 1, awaitTime   1), (2*(awaitTime   1)).minutes)
        }
    }
}

CodePudding user response:

Yeah, you should use flatMap. Await is bad even inside a Future (in some way, it is actually worse). It is likely what is causing your immediate problem too (first few queries exhaust all the threads in the pool, and then Await blocks forever).

Try doing it in a truly asynchronous way:

  def doQuery(params: Foo, maxTries: Int) = client.query("gql", params).result.flatMap { 
     case Right(r) if r.nonEmpty  => Future.successful(r -> "stringmessage")
     case _ if maxTries == 1 => Future.successful(Nil -> "stringmessage")
     case _ => doQuery(params, maxTries-1)
   }
  • Related