=str fix sub-upstream cancellation in concatAll
- ActorProcessor terminated eagerly when ConcatAll had just taken up a new input stream but not yet received onSubscribe for it - The ActorProcessor eagerly shuts itself down upon onError and that cannot be changed without completely reworking the Pump, so I opted for just tracking the outstanding substreamSubscribers that have not yet seen OnSubscribe and making them cancel properly when that arrives (possibly later).
This commit is contained in:
parent
6e72271eb5
commit
d462cdd1b4
16 changed files with 115 additions and 45 deletions
|
|
@ -17,7 +17,7 @@ class ActorInterpreterLifecycleSpec extends AkkaSpec with InterpreterLifecycleSp
|
|||
implicit val mat = ActorFlowMaterializer()
|
||||
|
||||
class Setup(ops: List[Stage[_, _]] = List(fusing.Map({ x: Any ⇒ x }, stoppingDecider))) {
|
||||
val up = TestPublisher.manualProbe[Int]
|
||||
val up = TestPublisher.manualProbe[Int]()
|
||||
val down = TestSubscriber.manualProbe[Int]
|
||||
private val props = ActorInterpreter.props(mat.settings, ops, mat).withDispatcher("akka.test.stream-dispatcher")
|
||||
val actor = system.actorOf(props)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class ActorInterpreterSpec extends AkkaSpec {
|
|||
implicit val mat = ActorFlowMaterializer()
|
||||
|
||||
class Setup(ops: List[Stage[_, _]] = List(fusing.Map({ x: Any ⇒ x }, stoppingDecider))) {
|
||||
val up = TestPublisher.manualProbe[Int]
|
||||
val up = TestPublisher.manualProbe[Int]()
|
||||
val down = TestSubscriber.manualProbe[Int]
|
||||
private val props = ActorInterpreter.props(mat.settings, ops, mat).withDispatcher("akka.test.stream-dispatcher")
|
||||
val actor = system.actorOf(props)
|
||||
|
|
|
|||
|
|
@ -71,6 +71,29 @@ class FlowConcatAllSpec extends AkkaSpec {
|
|||
subUpstream.expectCancellation()
|
||||
}
|
||||
|
||||
"on onError on master stream cancel the currently opening substream and signal error" in assertAllStagesStopped {
|
||||
val publisher = TestPublisher.manualProbe[Source[Int, _]]()
|
||||
val subscriber = TestSubscriber.manualProbe[Int]()
|
||||
Source(publisher).flatten(FlattenStrategy.concat).to(Sink(subscriber)).run()
|
||||
|
||||
val upstream = publisher.expectSubscription()
|
||||
val downstream = subscriber.expectSubscription()
|
||||
downstream.request(1000)
|
||||
|
||||
val substreamPublisher = TestPublisher.manualProbe[Int](autoOnSubscribe = false)
|
||||
val substreamFlow = Source(substreamPublisher)
|
||||
upstream.expectRequest()
|
||||
upstream.sendNext(substreamFlow)
|
||||
val subUpstream = substreamPublisher.expectSubscription()
|
||||
|
||||
upstream.sendError(testException)
|
||||
|
||||
subUpstream.sendOnSubscribe()
|
||||
|
||||
subscriber.expectError(testException)
|
||||
subUpstream.expectCancellation()
|
||||
}
|
||||
|
||||
"on onError on open substream, cancel the master stream and signal error " in assertAllStagesStopped {
|
||||
val publisher = TestPublisher.manualProbe[Source[Int, _]]()
|
||||
val subscriber = TestSubscriber.manualProbe[Int]()
|
||||
|
|
@ -112,6 +135,29 @@ class FlowConcatAllSpec extends AkkaSpec {
|
|||
upstream.expectCancellation()
|
||||
}
|
||||
|
||||
"on cancellation cancel the currently opening substream and the master stream" in assertAllStagesStopped {
|
||||
val publisher = TestPublisher.manualProbe[Source[Int, _]]()
|
||||
val subscriber = TestSubscriber.manualProbe[Int]()
|
||||
Source(publisher).flatten(FlattenStrategy.concat).to(Sink(subscriber)).run()
|
||||
|
||||
val upstream = publisher.expectSubscription()
|
||||
val downstream = subscriber.expectSubscription()
|
||||
downstream.request(1000)
|
||||
|
||||
val substreamPublisher = TestPublisher.manualProbe[Int](autoOnSubscribe = false)
|
||||
val substreamFlow = Source(substreamPublisher)
|
||||
upstream.expectRequest()
|
||||
upstream.sendNext(substreamFlow)
|
||||
val subUpstream = substreamPublisher.expectSubscription()
|
||||
|
||||
downstream.cancel()
|
||||
|
||||
subUpstream.sendOnSubscribe()
|
||||
|
||||
subUpstream.expectCancellation()
|
||||
upstream.expectCancellation()
|
||||
}
|
||||
|
||||
"pass along early cancellation" in assertAllStagesStopped {
|
||||
val up = TestPublisher.manualProbe[Source[Int, _]]()
|
||||
val down = TestSubscriber.manualProbe[Int]()
|
||||
|
|
|
|||
|
|
@ -258,8 +258,8 @@ class FlowGraphCompileSpec extends AkkaSpec {
|
|||
|
||||
"build with implicits and variance" in {
|
||||
FlowGraph.closed() { implicit b ⇒
|
||||
def appleSource = b.add(Source(TestPublisher.manualProbe[Apple]))
|
||||
def fruitSource = b.add(Source(TestPublisher.manualProbe[Fruit]))
|
||||
def appleSource = b.add(Source(TestPublisher.manualProbe[Apple]()))
|
||||
def fruitSource = b.add(Source(TestPublisher.manualProbe[Fruit]()))
|
||||
val outA = b add Sink(TestSubscriber.manualProbe[Fruit]())
|
||||
val outB = b add Sink(TestSubscriber.manualProbe[Fruit]())
|
||||
val merge = b add Merge[Fruit](11)
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ class FlowStageSpec extends AkkaSpec(ConfigFactory.parseString("akka.actor.debug
|
|||
downstream.cancel()
|
||||
onDownstreamFinishProbe.expectMsg("onDownstreamFinish")
|
||||
|
||||
val up = TestPublisher.manualProbe[Int]
|
||||
val up = TestPublisher.manualProbe[Int]()
|
||||
up.subscribe(s)
|
||||
val upsub = up.expectSubscription()
|
||||
upsub.expectCancellation()
|
||||
|
|
|
|||
|
|
@ -570,7 +570,7 @@ class GraphFlexiMergeSpec extends AkkaSpec {
|
|||
}
|
||||
|
||||
"propagate failure" in assertAllStagesStopped {
|
||||
val publisher = TestPublisher.manualProbe[String]
|
||||
val publisher = TestPublisher.manualProbe[String]()
|
||||
val completionProbe = TestProbe()
|
||||
val p = FlowGraph.closed(out) { implicit b ⇒
|
||||
o ⇒
|
||||
|
|
@ -587,7 +587,7 @@ class GraphFlexiMergeSpec extends AkkaSpec {
|
|||
}
|
||||
|
||||
"emit failure" in assertAllStagesStopped {
|
||||
val publisher = TestPublisher.manualProbe[String]
|
||||
val publisher = TestPublisher.manualProbe[String]()
|
||||
val completionProbe = TestProbe()
|
||||
val p = FlowGraph.closed(out) { implicit b ⇒
|
||||
o ⇒
|
||||
|
|
@ -607,7 +607,7 @@ class GraphFlexiMergeSpec extends AkkaSpec {
|
|||
}
|
||||
|
||||
"emit failure for user thrown exception" in assertAllStagesStopped {
|
||||
val publisher = TestPublisher.manualProbe[String]
|
||||
val publisher = TestPublisher.manualProbe[String]()
|
||||
val completionProbe = TestProbe()
|
||||
val p = FlowGraph.closed(out) { implicit b ⇒
|
||||
o ⇒
|
||||
|
|
@ -626,7 +626,7 @@ class GraphFlexiMergeSpec extends AkkaSpec {
|
|||
}
|
||||
|
||||
"emit failure for user thrown exception in onComplete" in assertAllStagesStopped {
|
||||
val publisher = TestPublisher.manualProbe[String]
|
||||
val publisher = TestPublisher.manualProbe[String]()
|
||||
val completionProbe = TestProbe()
|
||||
val p = FlowGraph.closed(out) { implicit b ⇒
|
||||
o ⇒
|
||||
|
|
@ -670,7 +670,7 @@ class GraphFlexiMergeSpec extends AkkaSpec {
|
|||
}
|
||||
|
||||
"support finish from onInput" in assertAllStagesStopped {
|
||||
val publisher = TestPublisher.manualProbe[String]
|
||||
val publisher = TestPublisher.manualProbe[String]()
|
||||
val completionProbe = TestProbe()
|
||||
val p = FlowGraph.closed(out) { implicit b ⇒
|
||||
o ⇒
|
||||
|
|
|
|||
|
|
@ -145,8 +145,8 @@ class GraphMergeSpec extends TwoStreamsSetup {
|
|||
}
|
||||
|
||||
"pass along early cancellation" in assertAllStagesStopped {
|
||||
val up1 = TestPublisher.manualProbe[Int]
|
||||
val up2 = TestPublisher.manualProbe[Int]
|
||||
val up1 = TestPublisher.manualProbe[Int]()
|
||||
val up2 = TestPublisher.manualProbe[Int]()
|
||||
val down = TestSubscriber.manualProbe[Int]()
|
||||
|
||||
val src1 = Source.subscriber[Int]
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ class SourceSpec extends AkkaSpec {
|
|||
|
||||
"Composite Source" must {
|
||||
"merge from many inputs" in {
|
||||
val probes = Seq.fill(5)(TestPublisher.manualProbe[Int])
|
||||
val probes = Seq.fill(5)(TestPublisher.manualProbe[Int]())
|
||||
val source = Source.subscriber[Int]
|
||||
val out = TestSubscriber.manualProbe[Int]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue