문제

What I have to do to still support fault tolerance when using Future as shown in code below?

...

override def receive = {

   case email: Email => Future {

      // Suppose here I got an exception. Without "Future", supervisor strategy 
      // works well restarting the actor   
      throw new MailException("ops!")

   }

}

Supervisor Strategy:

...
withSupervisorStrategy(
   OneForOneStrategy(

 // Max number of retries
 maxNrOfRetries = retries,
 // Time Window
 withinTimeRange = timeRange) {

 case ex: MailException => {
   Restart
 }

}))
도움이 되었습니까?

해결책

It can get a bit complicated, because the Actor has likely processed other messages by the time the Future is complete.

What does it even mean for the Future to fail in this case? If it means that the Actor is corrupt and should be restarted then what's the validity of messages that were processed in the interim?

It all comes down to context, and what exactly is going on in your Actor + Future, but it pretty much boils down to two choices:

  1. The Actor is still valid and doesn't need restarting, but you still need to perform some explicit error handling/recovery for the future's result

  2. The Actor is invalid. I'll presume here that all interim messages would also be handled in Futures which will also fail. When one future fails you could send the actor a message that will cause it to throw an exception to be picked up by your supervisor strategy...

    ... Of course, things get quickly complicated with choice #2. You have to consider multiple Futures failing in a row. How do you prevent multiple restart messages? How do you cope if a future was initiated before a restart but fails afterwards?

TL;DR - Using Futures in Actors like this does not interact nicely with supervision. Don't do things in a Future that could potentially require a restart; try using pooled actors or nested worker actors instead.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top