pekko/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeKeepAlive.scala
Roland Kuhn 556012b7ee !str,htc replace and remove OneBoundedInterpreter
main work by @drewhk with contributions from @2m and @rkuhn

This work uncovered many well-hidden bugs in existing Stages, in
particular StatefulStage. These were hidden by the behavior of
OneBoundedInterpreter that normally behaves more orderly than it
guarantees in general, especially with respect to the timeliness of
delivery of upstream termination signals; the bugs were then that
internal state was not flushed when onComplete arrived “too early”.
2015-11-01 14:53:52 +01:00

77 lines
2.2 KiB
Scala

package docs.stream.cookbook
import akka.stream.ClosedShape
import akka.stream.scaladsl._
import akka.stream.testkit._
import akka.util.ByteString
class RecipeKeepAlive extends RecipeSpec {
"Recipe for injecting keepalive messages" must {
"work" in {
type Tick = Unit
val tickPub = TestPublisher.probe[Tick]()
val dataPub = TestPublisher.probe[ByteString]()
val sub = TestSubscriber.manualProbe[ByteString]()
val ticks = Source(tickPub)
val dataStream = Source(dataPub)
val keepaliveMessage = ByteString(11)
val sink = Sink(sub)
//#inject-keepalive
val tickToKeepAlivePacket: Flow[Tick, ByteString, Unit] = Flow[Tick]
.conflate(seed = (tick) => keepaliveMessage)((msg, newTick) => msg)
val graph = RunnableGraph.fromGraph(FlowGraph.create() { implicit builder =>
import FlowGraph.Implicits._
val unfairMerge = builder.add(MergePreferred[ByteString](1))
// If data is available then no keepalive is injected
dataStream ~> unfairMerge.preferred
ticks ~> tickToKeepAlivePacket ~> unfairMerge ~> sink
ClosedShape
})
//#inject-keepalive
graph.run()
val subscription = sub.expectSubscription()
// FIXME RK: remove (because I think this cannot deterministically be tested and it might also not do what it should anymore)
tickPub.sendNext(())
// pending data will overcome the keepalive
dataPub.sendNext(ByteString(1))
dataPub.sendNext(ByteString(2))
dataPub.sendNext(ByteString(3))
subscription.request(1)
sub.expectNext(ByteString(1))
subscription.request(2)
sub.expectNext(ByteString(2))
// This still gets through because there is some intrinsic fairness caused by the FIFO queue in the interpreter
// Expecting here a preferred element also only worked true accident with the old Pump.
sub.expectNext(keepaliveMessage)
subscription.request(1)
sub.expectNext(ByteString(3))
subscription.request(1)
tickPub.sendNext(())
sub.expectNext(keepaliveMessage)
dataPub.sendComplete()
tickPub.sendComplete()
sub.expectComplete()
}
}
}