AkkaCQRS icon indicating copy to clipboard operation
AkkaCQRS copied to clipboard

Checking for termination

Open varghesep opened this issue 9 years ago • 3 comments

In the line 74 of AggregateCoordinator, there is a check for the terminated message. I can presume why there is a check, because the actor has to be removed from the list.

But I don't know why there is a check for pending commands from line 81 that done inside the block. Shouldn't the actor be recreated anytime there is a command for an actor and if it does not exist? In that case, shouldn't the code be from 81 to 91 outside of the if block as shown below?

     protected override bool Receive(object message) 
     { 
         var terminated = message as Terminated; 
         if (terminated != null) 
         { 
             // if Terminated message was received, remove terminated actor from terminating children list 
             _terminatingChildren.ExceptWith(new[] { terminated.ActorRef }); 
          }
         else 
         {
             // if there were pending commands waiting to be sent to terminated actor, recreate it 
             var groups = _pendingCommands.GroupBy(cmd => cmd.PersistenceId == terminated.ActorRef.Path.Name).ToArray(); 
             _pendingCommands = groups.First(x => !x.Key).ToList(); 
             var commands = groups.First(x => x.Key); 
             foreach (var pendingCommand in commands) 
             { 
                 var child = Recreate(pendingCommand.AggregateId, pendingCommand.PersistenceId); 
                 child.Tell(pendingCommand.Command, pendingCommand.Sender); 
             } 

             return true; 
         } 

         return false; 
     } 

varghesep avatar Jun 28 '15 23:06 varghesep

The sole purpose of the default AggregateCoordinator.Receive method is to react on the Terminated actor messages, nothing else. Business rules concerned with forwarding messages are handled in classes inheriting from AggregateCoordinator.

Horusiath avatar Jun 29 '15 05:06 Horusiath

I'm sorry to ask this again because I don't understand why there is a special processing of waiting commands after an actor is terminated.

As I understand about the termination, there is a delay from the time an actor is asked to terminate and when the actor is really terminated and the terminated message is sent. In that duration a new command can arrive.

After an actor is terminated, can any pending commands reached before termination, during the termination and after termination consider as regular commands and recreate the actor if necessary and ask the actor to process? This way, there is no need of running the pending commands when a terminated message is arrived but outside of the if block.

Could you please clarify why you had to process the pending commands as you have done?

varghesep avatar Jun 29 '15 12:06 varghesep

Each actor has it's internal mailbox to buffer incoming messages. Problem is that after sending a Stop message to actor's mailbox, there may be still some messages posted to it, before it will be terminated. When that occurs, any messages waiting inside actor's mailbox will be dropped into DeadLetters. In fact that means, they would be lost.

Therefore aggregate coordinator's role is to buffer messages send to dying children in order to resend them later after coordinator will resurrect the child. This is one of the easier implementations of a pattern called Passivate.

Horusiath avatar Jun 29 '15 13:06 Horusiath