Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle multiple Promises in an (akka) Actor?

Tags:

scala

akka

actor

I have an Akka actor responsible of handling http calls. I use scala dispatch to send multiple HTTP requests over an API:

urls.foreach { u
  val service = url(u)
  val promise = Http(service OK as.String).either
  for(p <- promise)
  {
     p match
     {
       case Left(error) =>
         faultHandler(error)
       case Right(result) =>
         resultHandler(result)
     }
  }

In the resultHandlerfunction, I increment an instance variable nbOfResults and compare to the number of calls I have done.

def resultHandler(result:String)
{
  this.nbOfResults++
  ...
  if(nbOfResults == nbOfCalls)
    // Do something
}

Is it safe ? May the nbOfResultsvaraible be accessed at the same time if two calls return their results simultaneously ?

For now, I believed that the actor is more or less equivalent to a thread and therefore the callback functions are not executed concurrently. Is it correct ?

like image 299
Yannick Chaze Avatar asked Dec 03 '12 17:12

Yannick Chaze


2 Answers

Here is a variant of Alexey Romanov response using only dispatch :

//Promises will be of type Array[Promise[Either[Throwable, String]]]
val promises = urls.map { u =>
    val service = url(u)

    Http(service OK as.String).either
}

//Http.promise.all transform an Iterable[Promise[A]] into Promise[Iterable[A]]
//So listPromise is now of type Promise[Array[Either[Throwable, String]]]
val listPromise = Http.promise.all(promises)

for (results <- listPromise) {
    //Here results is of type Array[Either[Throwable, String]]

    results foreach { result =>
        result match {
            Left(error) => //Handle error
            Right(response) => //Handle response
        }
    }
}
like image 93
mravey Avatar answered Nov 15 '22 06:11

mravey


There is a far better way:

val promises = urls.map {u =>
  val service = url(u)
  val promise = Http(service OK as.String).either
}

val listPromise = Future.sequence(promises)

listPromise.onComplete { whatever }
like image 20
Alexey Romanov Avatar answered Nov 15 '22 06:11

Alexey Romanov