=str #17407: MapAsync should pull when failed futures free up space

This commit is contained in:
Endre Sándor Varga 2015-05-07 15:05:29 +02:00
parent 9125a719fe
commit 7f6a67a5c0
3 changed files with 38 additions and 6 deletions

View file

@ -396,25 +396,27 @@ private[akka] final case class MapAsync[In, Out](parallelism: Int, f: In ⇒ Fut
}
override def onPull(ctx: AsyncContext[Out, (Int, Try[Out])]) = {
@tailrec def rec(hasFreedUpSpace: Boolean): DownstreamDirective =
@tailrec def rec(): DownstreamDirective =
if (elemsInFlight.isEmpty && ctx.isFinishing) ctx.finish()
else if (elemsInFlight.isEmpty || elemsInFlight.peek == NotYetThere) {
if (hasFreedUpSpace && ctx.isHoldingUpstream) ctx.holdDownstreamAndPull()
if (!elemsInFlight.isFull && ctx.isHoldingUpstream) ctx.holdDownstreamAndPull()
else ctx.holdDownstream()
} else elemsInFlight.dequeue() match {
case Failure(ex) rec(true)
case Failure(ex) rec()
case Success(elem)
if (ctx.isHoldingUpstream) ctx.pushAndPull(elem)
else ctx.push(elem)
}
rec(false)
rec()
}
override def onAsyncInput(input: (Int, Try[Out]), ctx: AsyncContext[Out, Notification]) = {
@tailrec def rec(): Directive =
if (elemsInFlight.isEmpty && ctx.isFinishing) ctx.finish()
else if (elemsInFlight.isEmpty || elemsInFlight.peek == NotYetThere) ctx.ignore()
else elemsInFlight.dequeue() match {
else if (elemsInFlight.isEmpty || (elemsInFlight.peek eq NotYetThere)) {
if (!elemsInFlight.isFull && ctx.isHoldingUpstream) ctx.pull()
else ctx.ignore()
} else elemsInFlight.dequeue() match {
case Failure(ex) rec()
case Success(elem)
if (ctx.isHoldingUpstream) ctx.pushAndPull(elem)