Acting template with Akka and lengthy processes

Recently, I have been studying the amazing structure of Akka in order to try to understand it and decide if this will be right for my project. Currently, this application is a regular old Java application that performs very complex calculations, making calls to various external C ++ executables (sometimes calculations can take several hours). In code, it will look something like this.

public static class Worker extends UntypedActor { // Run Very Long Process public void onReceive(Object message) { if (message instanceof Work) { Work work = (Work) message; double result = veryLongProcess(work.getStart(),work.getNrOfElements()); getSender().tell(new Result(result), getSelf()); } else { unhandled(message); } } } 

My question is: can Akka handle the actors, sometimes taking hours to return from their performance?

+5
source share
2 answers

Answering your question directly; There is a good article in this thread:

Again, if you have lengthy calculations, if they run in a separate ExecutionContext for tasks related to the CPU, it is a good idea.

The article provides an example:

 import java.util.concurrent.Executors import concurrent.ExecutionContext //I added 'private' for the rest of the example private val executorService = Executors.newFixedThreadPool(4) private val executionContext = ExecutionContext.fromExecutorService(executorService) 

The answer is indirectly

Futures first

I completely agree that Akka Actors is a very useful tool for specific types of work. When it comes to caching, Actors and Agents are the best game in town.

However, in this case, I would suggest using Future instead of the Actor. You can make the function veryLongProcess a private . Confidentiality will allow full control over the number of threads calling the method immediately:

 def longProcessFut(start : Int, noOfElements : Int) : Future[Result] = Future { veryLongProcess(start, noOfElements) }(executionContext)//controls the executing pool of veryLongProcess 

Simple, concise and asynchronous.

There is no killing of letters, no overloaded reception method that takes anything under the sun, as well as props, even for ActorRef there was no need for the future. Bloom, beer belly, I say!

In addition, your user is going to create the Future no matter what ? :

 //Actor user code, too verbose val longProcessRef = actorSystem actorOf Props[Worker] val fut : Future[Result] = (longProcessRef ? Work(0,42)).mapTo[Result] 

Compared to using direct futures

 //happy user code val fut : Future[Result] = longProcessFut(0, 42) 

The same great future, but half the calories!

You can control the controller of the Future in the same way as suggested in the comments, which is pretty good. You can even use actorSystem.dispatcher as a future dispatcher to control the behavior of the dispatcher.

+2
source

If the long business logic / algorithm is incremental, it produces intermediate results and / or can work for a very long time, then you can reuse excellent fragments of the design from here: Incremental chord processing acc

0
source

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


All Articles