Reputation: 3183
The Future[Response].value
: Option[Try[Response]]
is always empty. Am I misunderstanding Futures? Do I need to wrap this in an onSuccess
? But then it won't return a String, but a Unit?
@tailrec private def initConnection: String =
{
val response: Future[Response] = initHeaders(WS.url(url)).post(authBody)
val retry: Boolean = {
response.value.isEmpty || response.value.get.isFailure || response.value.get.get.header("ConnectionID").isEmpty
}
if (!retry) return response.value.get.get.header("ConnectionID").get
else initConnection
}
Upvotes: 0
Views: 494
Reputation: 5974
Future#value
does not block on the future. If the future is already completed at the time of calling value
, you will get Some(_)
, otherwise it will be None
. So you see only None
since you check the value
immediately after sending the request and it hasn't finished yet. You can use future combinators like collect
and recoverWith
to implement the retry functionality and return a Future[String]
instead of a String
. If you really need the value later, you will have to Await.result
the future.
import scala.util.control.NonFatal
import scala.concurrent.Await
private def initConnectionFuture: Future[String] =
initHeaders(WS.url(url)).post(authBody).collect {
case response if response.header("ConnectionID").isDefined =>
response.header("ConnectionID").get
}.recoverWith {
case NonFatal(_) => initConnectionFuture
}
private def initConnection: String =
Await.result(initConnectionFuture, 5 seconds) // or any other acceptable timeout
In addition to the timeout, you might also want to limit the number of retries, e.g.
private def initConnectionFuture(retries: Int = 5): Future[String] =
initHeaders(WS.url(url)).post(authBody).collect {
case response if response.header("ConnectionID").isDefined =>
response.header("ConnectionID").get
}.recoverWith {
case NonFatal(_) if retries > 0 => initConnectionFuture(retries - 1)
}
Upvotes: 2