Future getting timed out on getting the akka http response - scala

m new to the concept of Futures and i'm getting a Future timed out exception when i'm trying to retrieve a HTTPResponse.
val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = sampleUrl).withHeaders(Authorization(validCredentials)))
val timeout = 2.seconds
responseFuture.flatMap { resp => resp.entity.toStrict(timeout) }.map { strictEntity => strictEntity.data.utf8String }
It works as intended for sometime on the cluster where its hosted and crashes, when I check the logs. It says Future timed out after 2 seconds. how do I correct this?

It seems like your sampleUrl is not consistently responding within 2 seconds. By default HTTP clients wait for up to 60 seconds before they fail to receive a response. Perhaps, you could set the Future timeout on the similar lines at 60 seconds.

Related

Akka Http: Exceeded configured max-open-requests value of [32]

I post some data to Server using the following code
def post(endpoint: String, entity: Strict) = {
Http().singleRequest(HttpRequest(uri = Notifier.notificationUrl + endpoint, method = HttpMethods.POST,
entity = entity)) onComplete {
case Success(response) => response match {
case HttpResponse(StatusCodes.OK, _, _, _) =>
log.info("communicated successfully with Server")
}
case Failure(response) =>
log.error("communicated failed with Server: {}", response)
}
}
This is called every 10 seconds when Notifier actor receives message as following
case ecMonitorInformation: ECMonitorInformation =>
post("monitor", httpEntityFromJson(ecMonitorInformation.toJson))
Problem?
I see that Initially (around 5 requests going to server) but then it hungs up, I do not see any logging, server does not receive any data. After a while on the client side, I see following
ERROR c.s.e.notification.Notifier - communicated failed with Server: java.lang.RuntimeException: Exceeded configured max-open-requests value of [32]
What is going on? How do I fix this issue?
I went through the docs and tried the following
val connectionFlow: Flow[HttpRequest, HttpResponse,
Future[Http.OutgoingConnection]] =
Http().outgoingConnection(host = "localhost", port = 8080)
and then
def httpPost(uri: String, httpEntity:Strict) {
val responseFuture: Future[HttpResponse] =
Source.single(HttpRequest(uri = "/monitor", method = HttpMethods.POST, entity=httpEntity))
.via(connectionFlow)
.runWith(Sink.head)
responseFuture onComplete {
case Success(response) => log.info("Communicated with Server: {}", response)
case Failure(failure) => log.error("Communication failed with Server: {}", failure)
}
and this worked for me
You can also overcome this error by upping the max-open-requests property of akka which is 32 by default.
The property to change will be:
akka.http.host-connection-pool.max-open-requests = 64
The only caveat is that this will fail when the client opens more concurrent connections than what the new value of that parameter is, in this example if the open connections exceed 64, you will get the same error.
If you are going to be repeatedly calling your method, you might want to consider using one of the connection pool based client methods as described here:
http://doc.akka.io/docs/akka-stream-and-http-experimental/1.0/scala/http/client-side/index.html
You can also set the connection pool settings in the akka-http client configuration:
http://doc.akka.io/docs/akka-stream-and-http-experimental/1.0/scala/http/configuration.html#akka-http-core
Search for host-connection-pool.
You could use Source.queue instead of Source.single to provide buffering and overflow strategy. See more details at https://stackoverflow.com/a/35115314/1699837

Do Play! 2 Action.async requests kill the future in the background when interrupted?

I've got the following Play! 2 Action.async controller:
def complexAlgorithm(graphId: String) = Action.async { implicit request =>
val f = future {
val data = new ComplexAlgorithm(GraphContext.get(graphId))
data.evaluate
data
}
f.map { result => Ok(Json.generate(result.getRankings.toList.filterNot(o => o.rankScore == 0))) }
}
I've realized that in some cases this computation is actually going to take more than an hour. Since this will be redesigned for production use, I'm OK with waiting for the result in the browser since it's logged anyways.
So my question is does the future above val f get killed if the browser request is interrupted? Say for instance, if the internet disconnects while waiting for a response? Or will it actually complete its calculation (even if hours later)?
Thanks!

Handle twitter4j User Stream 420 Exception

The actual problem is this: I open up a User Stream to populate some cache of mine, some times, this stream gets a 420 exception (Too many login attempts in a short period of time.)
How long should I wait before trying to reestablish connection?
override def onException(ex: Exception): Unit = {
Logger.info("Exception:::" + ex.getMessage + ":::" + ex.getCause)
if (ex.getMessage.startsWith("420")) {
// Can't authenticate for now, thus has to fill up cache hole in next start
// Wait some time (How long?) Thread.sleep(5000L)
// Connect via restApi and fill up the holes in the cache
// Continue listening
}
}
I suppose you would have to use some backoff strategy here, also I wouldn't use sleep, I would keep my application asynchronous.
This probably is not strictly a solution to your problem since it's almost considerable pseudo code, but it could be a start. First I borrow from Play! the timeout future definition:
import scala.language.higherKinds
import scala.concurrent.duration.FiniteDuration
import java.util.concurrent.TimeUnit
import scala.concurrent.{ExecutionContext, Future, Promise => SPromise}
import play.api.libs.concurrent.Akka
import util.Try
def timeout[A](message: => A, duration: Long, unit: TimeUnit = TimeUnit.MILLISECONDS)(implicit ec: ExecutionContext): Future[A] = {
val p = SPromise[A]()
Akka.system.scheduler.scheduleOnce(FiniteDuration(duration, unit)) {
p.complete(Try(message))
}
p.future
}
This uses Akka to schedule a future execution and combined with a promise returns a future. At this point you could chain future execution using flatMap on the timeout future:
val timeoutFuture: Future[String] =
timeout("timeout", duration, TimeUnit.SECONDS)
timeoutFuture.flatMap(timeoutMessage => connectToStream())
At this point the connection is executed only after the timeout has expired but we still need to implement some kind of reconnection mechanism, for that we can use recover:
def twitterStream(duration: Long = 0, retry: Int = 0): Future[Any] = {
val timeoutFuture: Future[String] =
timeout("timeout", duration, TimeUnit.SECONDS)
// check how many time we tried to implement some stop trying strategy
// check how long is the duration and if too long reset.
timeoutFuture.flatMap(timeoutMessage => connectToStream())
.recover {
case connectionLost: SomeConnectionExpiredException =>
twitterStream(duration + 20, retry + 1) // try to reconnect
case ex: Exception if ex.getMessage.startsWith("420") =>
twitterStream(duration + 120, retry + 1) // try to reconect with a longer timer
case _ =>
someDefault()
}
}
def connectToStream(): Future[String] = {
// connect to twitter
// do some computation
// return some future with some result
Future("Tweets")
}
What happens here is that when an exception is catched from the future and if that exception is a 420 or some connection lost exception the recover is executed and the function is re-called restarting the connection after duration + 20 seconds.
A couple of notes, the code is untested (I could only compile it), also the backoff time here is linear (x + y), you may want to have a look at some exponential backoff strategy and lastly you will need Akka to implement the schedule once used in the timeout future (Play has already Akka available), for other possibility of using timeout on futures check this SO question.
Not sure if all this is overkill, probably there are shorter and easier solutions.

Throttle HTTP request on Akka/Spray

I'm using Akka actors in Scala to download resources from external service (HTTP get request). Response from external service is JSON and I have to use paging (provider is very slow). I want to download all paged results concurrently in 10 threads. I use an URL such as this to download chunk: http://service.com/itmes?limit=50&offset=1000
I have created following pipeline:
ScatterActor => RoundRobinPool[10](LoadChunkActor) => Aggreator
ScatterActor takes total count of items to download and divides it into chunks. I created 10 LoadChunkActor's to process tasks concurrently.
override def receive: Receive = {
case LoadMessage(limit) =>
val offsets: IndexedSeq[Int] = 0 until limit by chunkSize
offsets.foreach(offset => context.system.actorSelection(pipe) !
LoadMessage(chunkSize, offset))
}
LoadChunkActor uses Spray to send request. Actor looks like this:
val pipeline = sendReceive ~> unmarshal[List[Items]]
override def receive: Receive = {
case LoadMessage(limit, offset) =>
val uri: String = s"http://service.com/items?limit=50&offset=$offset"
val responseFuture = pipeline {Get(uri)}
responseFuture onComplete {
case Success(items) => aggregator ! Loaded(items)
}
}
As you can see, LoadChunkActor is requesting chunk from external service and adding callback to be run onComplete. Actor is now ready to take another message and he is requesting another chunk. Spray is using nonblocking API to download chunks. In result external service is flooded with my requests and I get timeouts.
How can I schedule list of tasks but I want to process maximum 10 at the same time?
I have created following solution (similar to pulling http://www.michaelpollmeier.com/akka-work-pulling-pattern/:
ScatterActor (10000x messages) =>
ThrottleActor => LoadChunkActor => ThrottleMonitorActor => Aggregator
^ |
|<--------WorkDoneMessage------------|
ThrottleActor pub messages into ListBuffer and sends to LoadChunkActor maximum N count of messages.
When LoadChunkActor sends message to Aggregator through ThrottleMonitorActor.
ThrottleMonitorActor sends confirmation to ThrottleActor.
ThrottleActor sends next message to LoadChunkActor.
From the project adhoclabs/akka-http-contrib, you now (July 2016, two years later) the scala.co.adhoclabs.akka.http.contrib.throttle package from Yeghishe Piruzyan.
See "Akka Http Request Throttling"
implicit val throttleSettings = MetricThrottleSettings.fromConfig
Http().bindAndHandle(
throttle.apply(routes),
httpInterface,
httpPort
)

Wait for response with timeout in "Dispatch" library

I am going to use Dispatch to write a simple HTTP client. I call dispatch.Http to get a future and call the future to get the response
val request = ...
val future = Http(request) // call the server asynchronously
val response = future() // wait for the response from the server
Now I wonder how I can wait with timeout. I would like the last API call to be:
// throw an exception if no response received within timeout
val response = future(timeout: Long)
Does it make sense ?
I understand that Dispatch return scala.concurrent.Future, which does not provide API with timeout. How would you suggest me implement it ?
You can create configured Http client:
val httpApplicationClient = Http.configure(
_.setRequestTimeoutInMs(3000)
)
val future = httpApplicationClient(request)
...
First, you can use Await:
import scala.concurrent.Await
import scala.concurrent.duration._
Await.result(future, 10 seconds) //you can specify timeout here
The problem is that it will throw an exception if the future did not manage to return in specified timeout.
If you need more flexibility here is the second approach:
val futureTimeout = Promise.timeout("Timed out" /* or throw new RuntimeException("timed out") */, 10 seconds)
Future.firstCompletedOf(Seq(futureResult, futureTimeout)).map {
case result: SomeType => //do something
case timedOut: SomeOtherType => //handle timeout
}