3
votes

I am just starting with Akka and I am trying to split some messy functions in more manageable pieces, each of which would be carried out by a different actor.

My task seems exactly what is suitable for the actor model. I have a tree of objects, which are saved in a database. Each node has some attributes; lets' concentrate on just one and call it wealth. The wealth of the children depends on the wealth of the parent. When one computes the wealth on a node, this should trigger a similar computation on the children. I want to collect all the updated instances of nodes and save them at the same time in the DB.

This seems easy: an actor just performs the computation and then starts another actor for each child of the current node. When all children send back a message with the results of the computation, the actor collects them, adds the current node and sends a message to the actor above him.

The problem is that I do not know a way to be sure that one has received a message from all the children. A trivial way would be to use a counter and increase it whenever a message from a child arrives.

But what happens if two independent parts of the system require such a computation to be performed and the same actor is reused? The actor will spawn twice as many children and the counting will not be reliable anymore. What I would need is to make sure that the same actor is not reused from the external system, but new actors are generated each time the computation is triggered.

Is this even possible? If not, is there some automatic mechanism in Akka to make sure that every child has performed its task?

Am I just using the actor model in a situation that is not suitable here? Essentially I am doing nothing more than could be done with functions - the actors themselves are stateless, but they allow me to simplify and parallelize the computation.

1
What's the reason for wanting to save all the updated nodes at the same time?Larsenal
Also, what is the approximate size of the tree? About how many nodes? Typically how deep?Larsenal
@Larsenal I have to save all the nodes in a single transaction for consistency. Of course I can open a transaction, start saving nodes and close it afterwards. But I prefer to have everything refentially transparent and a single save action at the end - among other things it becomes easier to test. About the size of the tree, it will not be very deep, typically 3 levels only. But it can be quite large. It is premature to give hard data at this point of development, but I expect that at the second level there will be hundreds or thousands of nodes, each one having only a handful of children.Andrea

1 Answers

3
votes

The way that you describe things, I think what you really want is a recursive function that returns a Future[Tree[NodeWealth]], the function would spawn a Future every time it is called and it would call itself for each child in the hierarchy, at the end of the function it would compose the Futures from those calls into a single Future[Result]. When the recursive function terminates and returns the Future[Tree[NodeWealth]] you can then compose it with another Future which updates your DB. Take a look at the Akka documentation here on Futures. And pay particular attention to the section "Composing Futures".

The composition of futures should allow you to avoid state and implement this easily.

Another option would be to use actors and futures, and use the ask pattern on child actors, compose the resulting futures into a single future which you return to the sender (parent actor). This is essentially the same thing, just intertwined with actors. I would probably only go this route if you are already representing your nodes as actors for some other reason.