What's the difference between Supervision.Rest

2019-09-04 05:57发布

问题:

what's the difference between Supervision.Restart and Supervision.Resume really ?

Here is the situation. I have 3 elements coming from the Source(List(1, 2, 3)). In runForeach I throw exception if element is 2. For Supervision.Restart I expected only 1 to be processed. But oddly I see 3 reaching sink. Why ? I'm using Akka 2.4.11

import akka.actor.{ActorRef, ActorSystem}
import akka.stream.{ActorMaterializer, ActorMaterializerSettings, OverflowStrategy, Supervision}
import akka.stream.scaladsl.Source

val decider: Supervision.Decider = {
  case _: NotImplementedError =>
    Supervision.Restart
  case _                      =>
    Supervision.Stop
}

implicit val system = ActorSystem("root")
implicit val executor = system.dispatcher
implicit val materializer = ActorMaterializer(ActorMaterializerSettings(system).withSupervisionStrategy(decider))(system)

Source(List(1, 2, 3))
  .map { v =>
    if (v == 2)
      throw new NotImplementedError
    v
  }
  .runForeach(println)

https://scalafiddle.io/sf/HSj01pO/3

回答1:

In your example your Flow is (also called FlowShape):

.map { v =>
  if (v == 2)
    throw new NotImplementedError
  v
}

The main difference is:

  • Supervision.Restart: a new instance of your actor will be created which will have the initial state of your class. The previous state will be lost. In your case it will be the state of your Flow.

  • Supervision.Resume: the same instance is reused with the previous state. In your case it will be the state of your Flow.

In your case, your Flow is stateless so there is no difference between Supervision.Restart and Supervision.Resume.

Since you have case _: NotImplementedError => Supervision.Restart, then 1 gets mapped and reaches the Sink. 2 throws a NotImplementedError which restarts your Flow, drops that message but does not stop your stream. And then 3 gets mapped and reaches the Sink. Therefore you should see in the output 1 and 3.