Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Akka. How to know that all children actors finished their job

Tags:

scala

akka

I created Master actor and child actors (created using router from Master).

Master receives some Job and splits this job into small tasks and sends them to child actors (to routees).

The problem I trying to solve is how I can properly notify my Master when child actors finished their job?

In some tutorials (Pi approximation and in example from Scala In Action book) the Master actor after receiving response from children trying to compare the size of initial array of task with size of received results:

if(receivedResultsFromChildren.size == initialTasks.size) {
    // it's mean children finished their job
}

But I think it is very bad, because if some child actor throws exception then it will not send result back to sender (back to Master), so this condition will never evaluate to true.

So how properly notify master that all children finished their jobs?

I think one of the option is to Broadcast(PoisonPill) to children and then listen to Terminated(router) message (using so-called deathWatch). Is it ok solution?

If using Broadcast(PoisonPill) is better, then should I register some supervising strategy which will stop some routee in case of exception? Because if exception occurs, then routee will be restarted as I know, and it's mean that Master actor will never receive Terminated(router). Is it correct?

like image 926
WelcomeTo Avatar asked Jan 09 '23 07:01

WelcomeTo


1 Answers

In Akka this is actually quite simple.

The successful children can send an ordinary reply message to the parent actor. The unexpected failures from failing actors can be caught in the supervision strategy and handled appropriately (e.g. by restarting the actor, or by stopping it and removing it from the list of actors to wait).

So it could look something like this:

var waitingFor = Set.empty[ActorRef]

override def preStart() = ??? // Start the children with their subtasks

override def supervisionStrategy = OneForOneStrategy() {
    case _ => {
       waitingFor -= sender()
       if (waitingFor.isEmpty) ??? // processing finished
       Stop
    }
}

override def receive = {
    case Reply => {
        waitingFor -= sender()
        if (waitingFor.isEmpty) ??? // processing finished
    }
}
like image 182
Gregor Raýman Avatar answered Jan 26 '23 12:01

Gregor Raýman