stream: filter out elements without demand

This will also mean that completion will not be blocked by elements that
will later be filtered out.

One particular use case of that would be a kind of partitioning use case,
where you put several streams behind a broadcast and each consumer will filter
out elements not handled there. In that case, the broadcast can get head-of-line
blocked when one of the consumers currently has no demand but also wouldn't
have to handle any elements because they would all be filtered out.
This commit is contained in:
Johannes Rudolph 2020-01-09 16:16:17 +01:00
parent b30f8746d3
commit c39dd6506e
No known key found for this signature in database
GPG key ID: 52AF1C9ABD77E6E5
3 changed files with 66 additions and 21 deletions

View file

@ -84,10 +84,10 @@ class InterpreterSpec extends StreamSpec with GraphInterpreterSpecKit {
Doubler(),
Filter((x: Int) => x != 0)) {
lastEvents() should be(Set.empty)
lastEvents() should be(Set(RequestOne))
downstream.requestOne()
lastEvents() should be(Set(RequestOne))
lastEvents() should be(Set.empty)
upstream.onNext(0)
lastEvents() should be(Set(RequestOne))
@ -96,10 +96,10 @@ class InterpreterSpec extends StreamSpec with GraphInterpreterSpecKit {
lastEvents() should be(Set(OnNext(1)))
downstream.requestOne()
lastEvents() should be(Set(OnNext(1)))
lastEvents() should be(Set(OnNext(1), RequestOne))
downstream.requestOne()
lastEvents() should be(Set(RequestOne))
lastEvents() should be(Set.empty)
upstream.onComplete()
lastEvents() should be(Set(OnComplete))
@ -109,22 +109,22 @@ class InterpreterSpec extends StreamSpec with GraphInterpreterSpecKit {
Filter((x: Int) => x != 0),
Doubler()) {
lastEvents() should be(Set.empty)
lastEvents() should be(Set(RequestOne))
downstream.requestOne()
lastEvents() should be(Set(RequestOne))
lastEvents() should be(Set.empty)
upstream.onNext(0)
lastEvents() should be(Set(RequestOne))
upstream.onNext(1)
lastEvents() should be(Set(OnNext(1)))
lastEvents() should be(Set(OnNext(1), RequestOne))
downstream.requestOne()
lastEvents() should be(Set(OnNext(1)))
downstream.requestOne()
lastEvents() should be(Set(RequestOne))
lastEvents() should be(Set.empty)
downstream.cancel()
lastEvents() should be(Set(Cancel(SubscriptionWithCancelException.NoMoreElementsNeeded)))
@ -152,22 +152,23 @@ class InterpreterSpec extends StreamSpec with GraphInterpreterSpecKit {
takeTwo,
Map((x: Int) => x + 1)) {
lastEvents() should be(Set.empty)
lastEvents() should be(Set(RequestOne))
downstream.requestOne()
lastEvents() should be(Set(RequestOne))
lastEvents() should be(Set.empty)
upstream.onNext(0)
lastEvents() should be(Set(RequestOne))
upstream.onNext(1)
lastEvents() should be(Set(OnNext(2)))
lastEvents() should be(Set(OnNext(2), RequestOne))
downstream.requestOne()
lastEvents() should be(Set(RequestOne))
lastEvents() should be(Set.empty)
upstream.onNext(2)
lastEvents() should be(Set(Cancel(SubscriptionWithCancelException.StageWasCompleted), OnComplete, OnNext(3)))
lastEvents() should be(
Set(RequestOne, Cancel(SubscriptionWithCancelException.StageWasCompleted), OnComplete, OnNext(3)))
}
"implement fold" in new OneBoundedSetup[Int](Fold(0, (agg: Int, x: Int) => agg + x)) {