4

The following code do a bunch of calls to an external API. This API does not allow more than 3 queries per second. syncCallToApi is a function provided by the api client library that do a synchronous request and returns the result.

What is the best way in Scala to concurrently call callToApi no more than 3 times per seconds while keeping the following semantics:

val ids = Seq(12980,2932,3441,42334,980,32,4531,7234)
val results: Seq[Item] = ids.map(id => syncCallToApi(id)) 
println(results)
FGRibreau
  • 7,021
  • 2
  • 39
  • 48

1 Answers1

8

You can use Akka Throttler. Link2

import akka.actor.{Props, Actor, ActorSystem}
import akka.contrib.throttle.Throttler._
import akka.contrib.throttle.TimerBasedThrottler
import akka.util.Timeout
import java.util.concurrent.TimeUnit
import scala.concurrent.duration._
import akka.pattern.ask
import Api._
import scala.concurrent.{Await, ExecutionContext, Future}
import ExecutionContext.Implicits.global

object Main extends App {
  implicit val timeout = Timeout(1 minute)
  val system = ActorSystem("system")
  val throttler = system.actorOf(Props(new TimerBasedThrottler(new Rate(3, Duration(1, TimeUnit.SECONDS)))))
  val worker = system.actorOf(Props(classOf[ExternalApiActor]))
  throttler ! SetTarget(Option(worker))


  val ids = Seq(12980,2932,3441,42334,980,32,4531,7234)
  val listOfFutures: Seq[Future[Item]] = ids.map { id =>
      ask(throttler, id).mapTo[Item]
    }
  val futureList: Future[Seq[Item]] = Future.sequence(listOfFutures)
  val results: Seq[Item] = Await.result(futureList, 1 minute)
  println(results)
  system.shutdown()
}

class ExternalApiActor extends Actor {
  def receive = {
    case id: Int => sender ! syncCallToApi(id)
  }
}

object Api {
  def syncCallToApi(number: Int): Item = {
    println(s"call the API with $number")
    Item(number)
  }
}

case class Item(id: Int)


//build.sbt
scalaVersion := "2.10.1"

libraryDependencies += "com.typesafe.akka" % "akka-contrib_2.10" % "2.1.4"
Schleichardt
  • 7,502
  • 1
  • 27
  • 37
  • 1
    Use Futures. http://www.scala-lang.org/api/current/index.html#scala.actors.Futures$ http://doc.akka.io/docs/akka/2.0.1/scala/futures.html – itsbruce Sep 09 '13 at 20:23