Use supervision in all places of Source.fromIterator, #25574 (#25601)

* it was noticed in Source.fromIterator depending on where the
  iterator throwed exception
* fromIterator, as many other things, is implemented with
  statefulMapConcat
* supervision was only used for exceptions in onPush and not
  in onPull, added it there also
This commit is contained in:
Patrik Nordwall 2018-09-19 11:06:24 +02:00 committed by Konrad `ktoso` Malawski
parent e73bc64ade
commit 63ceb52bbd
3 changed files with 53 additions and 16 deletions

View file

@ -18,16 +18,17 @@ import akka.stream.impl.{ ReactiveStreamsCompliance, Buffer ⇒ BufferImpl }
import akka.stream.scaladsl.{ Flow, Keep, Source }
import akka.stream.stage._
import akka.stream.{ Supervision, _ }
import scala.annotation.tailrec
import scala.collection.immutable
import scala.collection.immutable.VectorBuilder
import scala.concurrent.{ Future, Promise }
import scala.util.control.{ NoStackTrace, NonFatal }
import scala.util.{ Failure, Success, Try }
import akka.stream.ActorAttributes.SupervisionStrategy
import akka.stream.ActorAttributes.SupervisionStrategy
import scala.concurrent.duration.{ FiniteDuration, _ }
import scala.util.control.Exception.Catcher
import akka.stream.impl.Stages.DefaultAttributes
import akka.util.OptionVal
@ -1938,19 +1939,28 @@ private[stream] object Collect {
try {
currentIterator = plainFun(grab(in)).iterator
pushPull()
} catch {
case NonFatal(ex) decider(ex) match {
case Supervision.Stop failStage(ex)
case Supervision.Resume if (!hasBeenPulled(in)) pull(in)
case Supervision.Restart
restartState()
if (!hasBeenPulled(in)) pull(in)
}
}
} catch handleException
override def onUpstreamFinish(): Unit = onFinish()
override def onPull(): Unit = pushPull()
override def onPull(): Unit =
try pushPull()
catch handleException
private def handleException: Catcher[Unit] = {
case NonFatal(ex) decider(ex) match {
case Supervision.Stop failStage(ex)
case Supervision.Resume
if (isClosed(in)) completeStage()
else if (!hasBeenPulled(in)) pull(in)
case Supervision.Restart
if (isClosed(in)) completeStage()
else {
restartState()
if (!hasBeenPulled(in)) pull(in)
}
}
}
private def restartState(): Unit = {
plainFun = f()