Run a list of acc actors for a message list

I am new to akka and I would like to run the list of acc actors right away for a list of posts, for example (I use scala here):

entrance

message_1 message_2 message_3 

for each message:

 1 2 3 

Starts 3 aka actors, immediately passing each parameter from the list to each of them, I would like to use these results later as a List answers. Ideally, I am looking for an operation that will give me the following:

 runActorsForListAndWaitForAnswer(messagesList).map(_.toInt()).sum 

I do not know if such a method exists, but that would be useful. Any help is appreciated, thanks!

+4
source share
1 answer

First of all, you need to abandon the imperative that blocks the mind. Akka wins best when everything is asynchronous. You should never block while waiting for another actor to respond. Instead, you can take a Future[T] object and apply a function to it. This function will be called when the future is done.

Make a simple example: you have a SquareActor that takes an Int and returns its square. The correct way to ask the answer is:

 squareActor ? 9 map {result => println(result) //81 } //more code 

Very important: a block of code with println will not be blocked. Next, the following code will be executed, and your callback method will be called after a while.

Believing that we can begin to use your use case. If I understand correctly, you have a list of participants and a list of integers. You want to send any integer to exactly one actor. Here is the pseudo code:

 val actors: List[ActorRef] = //... val numbers: List[Int] = //... val actorsWithArguments: List[(ActorRef, Int)] = actors zip numbers val futuresOfAny: List[Future[Any]] = actorsWithArguments map { case (actor, number) => actor ? number} val futures: List[Future[Int]] = futuresOfAny map {_.mapTo[Int]} val futureOfAllResults: Future[List[Int]] = Future.sequence(futures) val future: Future[Int] = futureOfAllResults map { _.sum} 

I intentionally left explicit types to help you execute the code. Release step by step:

  • actorsWithArguments is a List tuples. Each element contains a pair of actors and a message - (actor1, message1) , (actor2, message2) , ...

  • futuresOfAny contains a list of Future results for calling actor ? number actor ? number . ? returns a Future[Any] , because: a) the result is not known (yet) and b) Akka does not know what the type of the result will be (response message)

  • futures strongly typed, since we know that every answer is Int . We just mapTo every Future[Any] to Future[Int]

  • futureOfAllResults uses a really amazing conversion from List[Future[Int]] to Future[List[Int]] . In other words, we simply turned the list of future results into a single future result with all the elements.

  • Future fulfills (will be in the future) your result.

If you think this is a lot of code, it was just for educational purposes. Chains and type of inference can do magic:

 val future = Future.sequence(actors zip numbers map { case (actor, number) => actor ? number} map { _.mapTo[Int]}) map { _.sum} } 

Finally, you got your result. Well, you will be taken to the future. Now, if you want to send this result to another actor, you simply say:

 future map {sum => otherActor ! sum} //or even... future map otherActor.! 

I highly recommend that you read the chapter on futures in the official documentation to make it all clear.

+13
source

All Articles