Play WS API: Throttling Request Parameters

I am using the async Play WS Scala API to request a RESTful service. I wonder how I could handle URLs containing Listthat are called through WSClient, but no more than one request per second (the service allows "only" 1 request per second per client). From a logical point of view, the idea is to get an element (URL) from the list, make a request, and then wait a certain amount of time before moving on to the next element in the list.

  • using the good old Thread.sleepin a non-blocking and asynchronous structure like Play is definitely a bad idea.
  • the same is possible for things like ScheduledThreadPoolExecutoror other methods that require new threads.

How could I compress the request speed without adversely affecting the asynchronous and thread-like nature of the game?

+3
source share
2 answers

Suppose you have a list of URLs that you are looking to select:

val urls = List(
  "http://www.google.com",
  "http://stackoverflow.com",
  "http://www.bing.com"
)

In Play 2.5.x, we can process them sequentially and use them akka.pattern.afterto force an asynchronous delay between each call. We are the flatMapresult of Futurea webservice request that it will return the same value in one second.

Future.traverse(urls) { url =>
  wsClient.url(url).get().flatMap { result =>
    // potentially process `result` here
    akka.pattern.after(1.second, actorSystem.scheduler)(Future.successful(result))
  }
} // returns Future[List[WSResponse]]

This requires the presence of WSClientboth a ActorSystemcomponent, as well as an implicit one ExecutionContextin the region.


In Play 2.4.x and earlier, you can do the same with Promise.timeout:

Future.traverse(urls) { url =>
  wsClient.url(url).get().flatMap { result =>
    // potentially process `result` here
    Promise.timeout(result, 1.second)
    akka.pattern.after(1.second, actorSystem.scheduler)(Future.successful(result))
  }
}
+4
source

Akka : http://doc.akka.io/docs/akka/current/scala/scheduler.html

Akka Play, .
, - :

val webserviceCall : Runnable = new Runnable {

    override def run(): Unit = {
        // do webservice call work
        // figure out if you need to make more webservice calls, and if you do:
        actorSystem.scheduler.scheduleOnce(0 seconds, 1 seconds, webserviceCall)
    }

}

actorSystem.scheduler.scheduleOnce(0 seconds, webserviceCall)

Akka, - : http://doc.akka.io/docs/akka/snapshot/contrib/throttle.html

( , Akka 2.3 ), , .

+1

Source: https://habr.com/ru/post/1696324/


All Articles