3

I have the following code:

class A extends Actor with ActorLogging {
  override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 2) { 
    case _ => log.info("An actor has been killed"); Restart 
  }

  val b = context.system.actorOf(Props[B], "b")

  def receive = {
    case _ => context.system.scheduler.schedule(5 seconds, 5 seconds, b, true)
  }
}

class B extends Actor with ActorLogging {
  def receive = { case true => self ! Kill }
}

After self ! Kill in an instance of actor A I don't see a message "An actor has been killed" and subsequent call to actor A generates "dead letters" message so there was no restart. Why is OneForOneStrategy not getting called?

It's strange in a way that I can just remove the whole OneForOneStrategy override and there are no changes in program behavior whatsoever.

src091
  • 2,807
  • 7
  • 44
  • 74

2 Answers2

7

val b = context.system.actorOf(Props[B], "b") should be changed to val b = context.actorOf(Props[B], "b") to make new actor a child, not a top-level actor.

src091
  • 2,807
  • 7
  • 44
  • 74
3

You're simultaneously restarting the actor "B" and then throwing an exception when you restart it. Remove the self ! true from your postRestart code. Otherwise, what do you expect to happen? You're sending it into an infinitely recursive restart loop.

Here's the order or the actions you're seeing to illustrate it:

  1. Create actor "A"
  2. Create actor "B"
  3. send true to A
  4. send true to B
  5. "B" throws exception at true message
  6. "A" restarts "B"
  7. after restart "B" sends itself true
  8. repeat step 5
wheaties
  • 35,646
  • 15
  • 94
  • 131
  • Ok, but what `maxNrOfRetries = 2` is supposed do then? I'm aware of infinite loop of course but I was thinking it should be terminated after two retries by parent actor `A` because of this very option. – src091 Mar 27 '14 at 15:16
  • @Anton Well, if `postRestart` was called that means the Actor was restarted successfully. So the number of retries was 1. – wheaties Mar 27 '14 at 15:32
  • I still don't get it. The way I see it should work like this: start -> fail -> restart #1 -> fail -> restart #2 -> fail -> stop because `maxNrOfRetries = 2`. Am I missing something? – src091 Mar 27 '14 at 15:44
  • 4
    @Anton The max number of retries is the max number of times an attempt is made to restart the Actor and is reset after a restart succeeds. It is not the max number of times an Actor is restarted. – wheaties Mar 27 '14 at 15:52
  • Ok, thanks. I've simplified my code and removed recursion since it's not really relevant to the essence of my question. – src091 Mar 27 '14 at 17:42