Search code examples
akka-streamakka-supervision

why akka-stream restart supervision doesn't restart but just resume


Consider this simple stream:

Source(1 to 5)
.mapAsync(1) { i =>
  if (i % 3 == 0) Future.failed(new Exception("I don't like 3"))
  else Future.successful(i)
}
.withAttributes(
  ActorAttributes.supervisionStrategy(Supervision.restartingDecider)
)
.runForeach(i => println(s"#$i"))

This actually prints

#1
#2
#4

Which is the same as with the resume strategy. I would expect the stream to restart after the failed future with the following output

#1
#2
#1
#2
...
  1. Why does the Resume and Restart strategy behaves the same way in this case?
  2. How can I restart the stream from start?

Solution

  • Question 1: the difference between resume and restart is that - with the latter - the failing stage is restarted, losing all accumulated internal state. (See docs for reference).

    In your case, you have a mapAsync stage with parallelism 1, so you effectively will never have any accumulated state. This results in resume and restart being equivalent in behaviour.

    Question 2: The semantic of supervision strategies in Akka streams are related to the specific stage that fails. A failed stage simply has no way to replay the elements that flowed in the past, as they are already gone - i.e. not held anywhere. No supervision strategy can give you that.

    What you are looking for is a restart of the whole stream which should be achievable with the recoverWithRetries combinator (docs). You can feed the same source again (Source(1 to 5)) to the combinator to have it replay those elements.