Question

I am using the redis-react-nb library with my akka application. Unfortunately, when a connection to redis lost the library will stop itself with context stop self

This means that my application receives a termination notification like so:

def receive: Actor.Receive = {
          case Terminated(actorRef) =>
            ...
        }

So I'm wondering what to do here. Ideally I want to restart all children actors so they will all be initialised with a new redis connection - basically resetting the actor system to its initial state.

Am I missing something conceptually? Or is there a way for an actor to restart all of it's children without receiving an exception? self ! RestartAll or something similar?

Was it helpful?

Solution

Another way to look at this is to say that the actor you are talking about depends on the redis actor, it cannot continue its work without it. In that case it would be appropriate to escalate that as a failure to its parent and let that do the restart. If you do not handle the Terminated message, then a DeathPactException will be thrown, but you will have to install an appropriate supervisorStrategy in the parent since the default for that one is to terminate the child. I would recommend defining and throwing a RedisFailedException when you receive the Terminated message.

OTHER TIPS

One of the possible solutions is take a look into implementation of SupervisorStrategy.Restart. Unfortunately the implementation uses InternalActorRef:

  final def restartChild(child: ActorRef, cause: Throwable, suspendFirst: Boolean): Unit = {
    val c = child.asInstanceOf[InternalActorRef]
    if (suspendFirst) c.suspend()
    c.restart(cause)
  }

So I assume there is no built-in solution and you should do it yourself.

  def receive = {
    case Terminated(actorRef) => self ! RestartAll
    case RestartAll =>
      context.children.foreach(_ ! PoisonPill)
      //start all necessary actors again
  }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top