From de982b06078cd8e17d9f585372b60da86509ef43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Endre=20S=C3=A1ndor=20Varga?= Date: Mon, 22 Dec 2014 12:43:01 +0100 Subject: [PATCH 1/3] +doc: Added section about buffering --- .../docs/stream/StreamBuffersRateSpec.scala | 60 +++++++++++++++ akka-docs-dev/rst/scala/stream-index.rst | 1 + akka-docs-dev/rst/scala/stream-rate.rst | 76 ++++++++++++++++++- akka-docs-dev/rst/stream-configuration.rst | 7 ++ akka-stream/src/main/resources/reference.conf | 15 ++-- 5 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala create mode 100644 akka-docs-dev/rst/stream-configuration.rst diff --git a/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala b/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala new file mode 100644 index 0000000000..8e4acd4764 --- /dev/null +++ b/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala @@ -0,0 +1,60 @@ +package docs.stream + +import akka.stream.{ OverflowStrategy, MaterializerSettings, FlowMaterializer } +import akka.stream.scaladsl._ +import akka.stream.testkit.AkkaSpec + +class StreamBuffersRateSpec extends AkkaSpec { + implicit val mat = FlowMaterializer() + + "Demonstrate pipelining" in { + //#pipelining + Source(1 to 3) + .map { i => println(s"A: $i"); i } + .map { i => println(s"B: $i"); i } + .map { i => println(s"C: $i"); i } + .runWith(Sink.ignore) + //#pipelining + } + + "Demonstrate buffer sizes" in { + //#materializer-buffer + val materializer = FlowMaterializer( + MaterializerSettings(system) + .withInputBuffer( + initialSize = 64, + maxSize = 64)) + //#materializer-buffer + + //#section-buffer + val flow = + Flow[Int] + .section(OperationAttributes.inputBuffer(initial = 1, max = 1)) { sectionFlow => + // the buffer size of this map is 1 + sectionFlow.map(_ * 2) + } + .map(_ / 2) // the buffer size of this map is the default + //#section-buffer + } + + "buffering abstraction leak" in { + //#buffering-abstraction-leak + import scala.concurrent.duration._ + case class Tick() + + FlowGraph { implicit b => + import FlowGraphImplicits._ + + val zipper = ZipWith[Tick, Int, Int]((tick, count) => count) + + Source(initialDelay = 1.second, interval = 1.second, () => "message!") + .conflate(seed = (_) => 1)((count, _) => count + 1) ~> zipper.right + + Source(initialDelay = 3.second, interval = 3.second, () => Tick()) ~> zipper.left + + zipper.out ~> Sink.foreach(println) + } + //#buffering-abstraction-leak + } + +} diff --git a/akka-docs-dev/rst/scala/stream-index.rst b/akka-docs-dev/rst/scala/stream-index.rst index 0a7c244710..038f68e7d8 100644 --- a/akka-docs-dev/rst/scala/stream-index.rst +++ b/akka-docs-dev/rst/scala/stream-index.rst @@ -16,4 +16,5 @@ Streams stream-integrations stream-io stream-cookbook + ../stream-configuration diff --git a/akka-docs-dev/rst/scala/stream-rate.rst b/akka-docs-dev/rst/scala/stream-rate.rst index 0ca5b14e31..a81ff2b23b 100644 --- a/akka-docs-dev/rst/scala/stream-rate.rst +++ b/akka-docs-dev/rst/scala/stream-rate.rst @@ -4,13 +4,87 @@ Buffers and working with rate ############################# +Akka Streams processing stages are asynchronous and pipelined by default which means that a stage, after handing out +an element to its downstream consumer is able to immediately process the next message. To demonstrate what we mean +by this, let's take a look at the following example: + +.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#pipelining + +Running the above example, one of the possible outputs looks like this: + +:: + + A: 1 + A: 2 + B: 1 + A: 3 + B: 2 + C: 1 + B: 3 + C: 2 + C: 3 + +Note that the order is *not* ``A:1, B:1, C:1, A:2, B:2, C:2,`` which would correspond to a synchronous execution model +where an element completely flows through the processing pipeline before the next element enters the flow. The next +element is processed by a stage as soon as it emitted the previous one. + +While pipelining in general increases throughput, in practice there is a cost of passing an element through the +asynchronous (and therefore thread crossing) boundary which is significant. To amortize this cost Akka Streams uses +a *windowed*, *batching* backpressure strategy internally. It is windowed because as opposed to a `Stop-And-Wait`_ +protocol multiple elements might be "in-flight" concurrently with requests for elements. It is also batching because +a new element is not immediately requested once an element has been drained from the window-buffer but multiple elements +are requested after multiple elements has been drained. This batching strategy reduces the communication cost of +propagating the backpressure signal through the asynchronous boundary. + +While this internal protocol is mostly invisible to the user (apart form its throughput increasing effects) there are +situations when these details get exposed. In all of our previous examples we always assumed that the rate of the +processing chain is strictly coordinated through the backpressure signal causing all stages to process no faster than +the throughput of the connected chain. There are tools in Akka Streams however that enable the rates of different segments +of a processing chain to be "detached" or to define the maximum throughput of the stream through external timing sources. +These situations are exactly those where the internal batching buffering strategy suddenly becomes non-transparent. + +.. _Stop-And-Wait: https://en.wikipedia.org/wiki/Stop-and-wait_ARQ +.. _Reactive Streams: http://reactive-streams.org/ + +.. _stream-buffers-scala: + Buffers in Akka Streams ======================= Internal buffers and their effect --------------------------------- -*TODO* +As we have explained, for performance reasons Akka Streams introduces a buffer for every processing stage. The purpose +of these buffers is solely optimization, in fact the size of 1 would be the most natural choice if there would be no +need for throughput improvements. Therefore it is recommended to keep these buffer sizes small, and increase them only +to a level that throughput requirements of the application require. Default buffer sizes can be set through configuration: + +:: + + akka.stream.materializer.max-input-buffer-size = 16 + +Alternatively they can be set by passing a :class:`MaterializerSettings` to the materializer: + +.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#materializer-buffer + +If buffer size needs to be set for segments of a Flow only, it is possible by defining a ``section()``: + +.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#section-buffer + +Here is an example of a code that demonstrate some of the issues caused by internal buffers: + +.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#buffering-abstraction-leak + +Running the above example one would expect the number *3* to be printed in every 3 seconds (the ``conflate`` step here +is configured so that it counts the number of elements received before the downstream ``ZipWith`` consumes them). What +is being printed is different though, we will see the number *1*. The reason for this is the internal buffer which is +by default 16 elements large, and prefetches elements before the ``ZipWith`` starts consuming them. It is possible +to fix this issue by changing the buffer size of ``ZipWith`` (or the whole graph) to 1. We will still see a leading +1 though which is caused by an initial prefetch of the ``ZipWith`` element. + +.. note:: + In general, when time or rate driven processing stages exhibit strange behavior, one of the first solution to try + should be to decrease the input buffer of the affected elements to 1. Explicit user defined buffers ----------------------------- diff --git a/akka-docs-dev/rst/stream-configuration.rst b/akka-docs-dev/rst/stream-configuration.rst new file mode 100644 index 0000000000..520a4c6387 --- /dev/null +++ b/akka-docs-dev/rst/stream-configuration.rst @@ -0,0 +1,7 @@ +.. _stream-config: + +############# +Configuration +############# + +.. literalinclude:: ../../akka-stream/src/main/resources/reference.conf \ No newline at end of file diff --git a/akka-stream/src/main/resources/reference.conf b/akka-stream/src/main/resources/reference.conf index aed47eb5c4..848ea8fb7e 100644 --- a/akka-stream/src/main/resources/reference.conf +++ b/akka-stream/src/main/resources/reference.conf @@ -18,15 +18,20 @@ akka { # When this value is left empty, the default-dispatcher will be used. dispatcher = "" - # Cleanup leaked publishers and subscribers when they are not used within a given deadline + # Cleanup leaked publishers and subscribers when they are not used within a given + # deadline subscription-timeout { - # when the subscription timeout is reached one of the following strategies on the "stale" publisher: - # cancel - cancel it (via `onError` or subscribing to the publisher and `cancel()`ing the subscription right away - # warn - log a warning statement about the stale element (then drop the reference to it) + # when the subscription timeout is reached one of the following strategies on + # the "stale" publisher: + # cancel - cancel it (via `onError` or subscribing to the publisher and + # `cancel()`ing the subscription right away + # warn - log a warning statement about the stale element (then drop the + # reference to it) # noop - do nothing (not recommended) mode = cancel - # time after which a subscriber / publisher is considered stale and eligible for cancelation (see `akka.stream.subscription-timeout.mode`) + # time after which a subscriber / publisher is considered stale and eligible + # for cancelation (see `akka.stream.subscription-timeout.mode`) timeout = 5s } From fc8560afa9e6b7496d415ee3f7d40412d46541ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Endre=20S=C3=A1ndor=20Varga?= Date: Mon, 22 Dec 2014 13:25:06 +0100 Subject: [PATCH 2/3] Added explicit buffers section --- .../docs/stream/StreamBuffersRateSpec.scala | 27 ++++++++++++ akka-docs-dev/rst/scala/stream-rate.rst | 44 +++++++++++++++++-- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala b/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala index 8e4acd4764..793d9d0a77 100644 --- a/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala +++ b/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala @@ -57,4 +57,31 @@ class StreamBuffersRateSpec extends AkkaSpec { //#buffering-abstraction-leak } + "explcit buffers" in { + trait Job + def inboundJobsConnector(): Source[Job] = Source.empty() + //#explicit-buffers-backpressure + // Getting a stream of jobs from an imaginary external system as a Source + val jobs: Source[Job] = inboundJobsConnector() + jobs.buffer(1000, OverflowStrategy.backpressure) + //#explicit-buffers-backpressure + + //#explicit-buffers-droptail + jobs.buffer(1000, OverflowStrategy.dropTail) + //#explicit-buffers-droptail + + //#explicit-buffers-drophead + jobs.buffer(1000, OverflowStrategy.dropHead) + //#explicit-buffers-drophead + + //#explicit-buffers-dropbuffer + jobs.buffer(1000, OverflowStrategy.dropBuffer) + //#explicit-buffers-dropbuffer + + //#explicit-buffers-error + jobs.buffer(1000, OverflowStrategy.error) + //#explicit-buffers-error + + } + } diff --git a/akka-docs-dev/rst/scala/stream-rate.rst b/akka-docs-dev/rst/scala/stream-rate.rst index a81ff2b23b..5402dcb4d1 100644 --- a/akka-docs-dev/rst/scala/stream-rate.rst +++ b/akka-docs-dev/rst/scala/stream-rate.rst @@ -44,7 +44,6 @@ of a processing chain to be "detached" or to define the maximum throughput of th These situations are exactly those where the internal batching buffering strategy suddenly becomes non-transparent. .. _Stop-And-Wait: https://en.wikipedia.org/wiki/Stop-and-wait_ARQ -.. _Reactive Streams: http://reactive-streams.org/ .. _stream-buffers-scala: @@ -83,13 +82,52 @@ to fix this issue by changing the buffer size of ``ZipWith`` (or the whole graph 1 though which is caused by an initial prefetch of the ``ZipWith`` element. .. note:: - In general, when time or rate driven processing stages exhibit strange behavior, one of the first solution to try + In general, when time or rate driven processing stages exhibit strange behavior, one of the first solutions to try should be to decrease the input buffer of the affected elements to 1. Explicit user defined buffers ----------------------------- -*TODO* +The previous section explained the internal buffers of Akka Streams used to reduce the cost of crossing elements through +the asynchronous boundary. These are internal buffers which will be very likely automatically tuned in future versions. +In this section we will discuss *explicit* user defined buffers that are part of the domain logic of the stream processing +pipeline of an application. + +The example below will ensure that 1000 jobs (but not more) are dequeued from an external (imaginary) system and +stored locally in memory - relieving the external system: + +.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-backpressure + +The next example will also queue up 1000 jobs locally, but if there are more jobs waiting +in the imaginary external systems, it makes space for the new element by +dropping one element from the *tail* of the buffer. Dropping from the tail is a very common strategy but +it must be noted that this will drop the *youngest* waiting job. If some "fairness" is desired in the sense that +we want to be nice to jobs that has been waiting for long, then this option can be useful. + +.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-droptail + +Here is another example with a queue of 1000 jobs, but it makes space for the new element by +dropping one element from the *head* of the buffer. This is the *oldest* +waiting job. This is the preferred strategy if jobs are expected to be +resent if not processed in a certain period. The oldest element will be +retransmitted soon, (in fact a retransmitted duplicate might be already in the queue!) +so it makes sense to drop it first. + +.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-drophead + +Compared to the dropping strategies above, dropBuffer drops all the 1000 +jobs it has enqueued once the buffer gets full. This aggressive strategy +is useful when dropped jobs are preferred to delayed jobs. + +.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-dropbuffer + +If our imaginary external job provider is a client using our API, we might +want to enforce that the client cannot have more than 1000 queued jobs +otherwise we consider it flooding and terminate the connection. This is +easily achievable by the error strategy which simply fails the stream +once the buffer gets full. + +.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-error Rate transformation =================== From beffbab6016977b3f250e18231ff3923f9085568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Endre=20S=C3=A1ndor=20Varga?= Date: Mon, 22 Dec 2014 16:56:11 +0100 Subject: [PATCH 3/3] added custom linear stages section --- akka-docs-dev/rst/images/stage_chain.png | Bin 0 -> 28293 bytes akka-docs-dev/rst/images/stage_conceptual.png | Bin 0 -> 22739 bytes akka-docs-dev/rst/images/stage_doubler.png | Bin 0 -> 18225 bytes akka-docs-dev/rst/images/stage_filter.png | Bin 0 -> 16165 bytes akka-docs-dev/rst/images/stage_map.png | Bin 0 -> 12562 bytes akka-docs-dev/rst/images/stages.svg | 1124 +++++++++++++++++ .../code/docs/stream/FlowStagesSpec.scala | 124 ++ .../docs/stream/StreamBuffersRateSpec.scala | 1 + akka-docs-dev/rst/scala/stream-customize.rst | 132 +- 9 files changed, 1374 insertions(+), 7 deletions(-) create mode 100644 akka-docs-dev/rst/images/stage_chain.png create mode 100644 akka-docs-dev/rst/images/stage_conceptual.png create mode 100644 akka-docs-dev/rst/images/stage_doubler.png create mode 100644 akka-docs-dev/rst/images/stage_filter.png create mode 100644 akka-docs-dev/rst/images/stage_map.png create mode 100644 akka-docs-dev/rst/images/stages.svg create mode 100644 akka-docs-dev/rst/scala/code/docs/stream/FlowStagesSpec.scala diff --git a/akka-docs-dev/rst/images/stage_chain.png b/akka-docs-dev/rst/images/stage_chain.png new file mode 100644 index 0000000000000000000000000000000000000000..4a97712093319191735dfb2941001c90aa5a387d GIT binary patch literal 28293 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 literal 0 HcmV?d00001 diff --git a/akka-docs-dev/rst/images/stage_conceptual.png b/akka-docs-dev/rst/images/stage_conceptual.png new file mode 100644 index 0000000000000000000000000000000000000000..1cec7e33f9e8409d0201eceaad1a766bccf1fdd2 GIT binary patch literal 22739 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 E0L1WIm;e9( literal 0 HcmV?d00001 diff --git a/akka-docs-dev/rst/images/stage_filter.png b/akka-docs-dev/rst/images/stage_filter.png new file mode 100644 index 0000000000000000000000000000000000000000..743b675dd0a1165d9ba4e300232bc3372e0538a2 GIT binary patch literal 16165 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 S6Brm67(8A5T-G@yGywo+U3BXJ literal 0 HcmV?d00001 diff --git a/akka-docs-dev/rst/images/stage_map.png b/akka-docs-dev/rst/images/stage_map.png new file mode 100644 index 0000000000000000000000000000000000000000..8d04b1be44599f171e2fb020734e13a6f8ace679 GIT binary patch literal 12562 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 P7#KWV{an^LB{Ts5vn1Lm literal 0 HcmV?d00001 diff --git a/akka-docs-dev/rst/images/stages.svg b/akka-docs-dev/rst/images/stages.svg new file mode 100644 index 0000000000..cbc02c63ff --- /dev/null +++ b/akka-docs-dev/rst/images/stages.svg @@ -0,0 +1,1124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + onPush(in,ctx) + onPull(ctx) + ctx.pull() + ctx.push(out) + PushPullStage + + + + Sink + + Source + + + + + + + + + + + + + + + + onPush(in,ctx) + onPull(ctx) + ctx.pull() + ctx.push(out) + Map + + f(in) + + + + + + + + onPush(in,ctx) + onPull(ctx) + ctx.pull() + ctx.push(out) + Filter + + if p(in) + if !p(in) + + + + + + + + onPush(in,ctx) + onPull(ctx) + ctx.pull() + ctx.push(out) + Duplicator + + in + if oneLeft + if !oneLeft + + + Source + + + + + + + + + + + + + onPush(in,ctx) + onPull(ctx) + ctx.pull() + ctx.push(out) + Map + + f(in) + + + + + + + + onPush(in,ctx) + onPull(ctx) + ctx.pull() + ctx.push(out) + Duplicator + + in + if oneLeft + if !oneLeft + + + + + + + + onPush(in,ctx) + onPull(ctx) + ctx.pull() + ctx.push(out) + Filter + + if p(in) + if !p(in) + + + + Sink + + diff --git a/akka-docs-dev/rst/scala/code/docs/stream/FlowStagesSpec.scala b/akka-docs-dev/rst/scala/code/docs/stream/FlowStagesSpec.scala new file mode 100644 index 0000000000..3b62c59e87 --- /dev/null +++ b/akka-docs-dev/rst/scala/code/docs/stream/FlowStagesSpec.scala @@ -0,0 +1,124 @@ +package docs.stream + +import akka.stream.FlowMaterializer +import akka.stream.scaladsl.{ RunnableFlow, Sink, Source, Flow } +import akka.stream.stage.PushPullStage +import akka.stream.testkit.AkkaSpec + +import scala.collection.immutable +import scala.concurrent.Await +import scala.concurrent.duration._ + +class FlowStagesSpec extends AkkaSpec { + //#import-stage + import akka.stream.stage._ + //#import-stage + + implicit val mat = FlowMaterializer() + + "stages demo" must { + + "demonstrate various PushPullStages" in { + + //#one-to-one + class Map[A, B](f: A => B) extends PushPullStage[A, B] { + override def onPush(elem: A, ctx: Context[B]): Directive = + ctx.push(f(elem)) + + override def onPull(ctx: Context[B]): Directive = + ctx.pull() + } + //#one-to-one + + //#many-to-one + class Filter[A](p: A => Boolean) extends PushPullStage[A, A] { + override def onPush(elem: A, ctx: Context[A]): Directive = + if (p(elem)) ctx.push(elem) + else ctx.pull() + + override def onPull(ctx: Context[A]): Directive = + ctx.pull() + } + //#many-to-one + + //#one-to-many + class Duplicator[A]() extends PushPullStage[A, A] { + private var lastElem: A = _ + private var oneLeft = false + + override def onPush(elem: A, ctx: Context[A]): Directive = { + lastElem = elem + oneLeft = true + ctx.push(elem) + } + + override def onPull(ctx: Context[A]): Directive = + if (!ctx.isFinishing) { + // the main pulling logic is below as it is demonstrated on the illustration + if (oneLeft) { + oneLeft = false + ctx.push(lastElem) + } else + ctx.pull() + } else { + // If we need to emit a final element after the upstream + // finished + if (oneLeft) ctx.pushAndFinish(lastElem) + else ctx.finish() + } + + + override def onUpstreamFinish(ctx: Context[A]): TerminationDirective = + ctx.absorbTermination() + + } + //#one-to-many + + val keyedSink = Sink.head[immutable.Seq[Int]] + val sink = Flow[Int].grouped(10).to(keyedSink) + + //#stage-chain + val runnable: RunnableFlow = Source(1 to 10) + .transform(() => new Filter(_ % 2 == 0)) + .transform(() => new Duplicator()) + .transform(() => new Map(_ / 2)) + .to(sink) + //#stage-chain + + Await.result(runnable.run().get(keyedSink), 3.seconds) should be(Seq(1, 1, 2, 2, 3, 3, 4, 4, 5, 5)) + + } + + "demonstrate various PushStages" in { + + import akka.stream.stage._ + + //#pushstage + class Map[A, B](f: A => B) extends PushStage[A, B] { + override def onPush(elem: A, ctx: Context[B]): Directive = + ctx.push(f(elem)) + } + + class Filter[A](p: A => Boolean) extends PushStage[A, A] { + override def onPush(elem: A, ctx: Context[A]): Directive = + if (p(elem)) ctx.push(elem) + else ctx.pull() + } + //#pushstage + } + + "demonstrate StatefulStage" in { + + //#doubler-stateful + class Duplicator[A]() extends StatefulStage[A, A] { + override val initial: StageState[A, A] = new StageState[A, A] { + override def onPush(elem: A, ctx: Context[A]): Directive = + emit(List(elem, elem).iterator, ctx) + } + } + //#doubler-stateful + + } + } + +} diff --git a/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala b/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala index 793d9d0a77..86bc87bd41 100644 --- a/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala +++ b/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala @@ -8,6 +8,7 @@ class StreamBuffersRateSpec extends AkkaSpec { implicit val mat = FlowMaterializer() "Demonstrate pipelining" in { + def println(s: Any) = () //#pipelining Source(1 to 3) .map { i => println(s"A: $i"); i } diff --git a/akka-docs-dev/rst/scala/stream-customize.rst b/akka-docs-dev/rst/scala/stream-customize.rst index 73d8caa803..2c7eee3304 100644 --- a/akka-docs-dev/rst/scala/stream-customize.rst +++ b/akka-docs-dev/rst/scala/stream-customize.rst @@ -4,24 +4,142 @@ Custom stream processing ######################## +While the processing vocabulary of Akka Streams is quite rich (see the :ref:`stream-cookbook-scala` for examples) it +is sometimes necessary to define new transformation stages either because some functionality is missing from the +stock operations, or for performance reasons. In this part we show how to build custom processing stages and graph +junctions of various kinds. + Custom linear processing stages =============================== -Using PushStage ---------------- - -*TODO* - +To extend the available transformations on a :class:`Flow` or :class:`Source` one can use the ``transform()`` method +which takes a factory function returning a :class:`Stage`. Stages come in different flavors swhich we will introduce in this +page. Using PushPullStage ------------------- -*TODO* +The most elementary transformation stage is the :class:`PushPullStage` which can express a large class of algorithms +working on streams. A :class:`PushPullStage` can be illustrated as a box with two "input" and two "output ports" as it is +seen in the illustration below. + +.. image:: ../images/stage_conceptual.png + :align: center + :width: 600 + +The "input ports" are implemented as event handlers ``onPush(elem,ctx)`` and ``onPull(ctx)`` while "output ports" +correspond to methods on the :class:`Context` object that is handed as a parameter to the event handlers. By calling +exactly one "output port" method we wire up these four ports in various ways which we demonstrate shortly. + +.. warning:: + There is one very important rule to remember when working with a ``Stage``. **Exactly one** method should be called + on the **currently passed** :class:`Context` **exactly once** and as the **last statement of the handler** where the return type + of the called method **matches the expected return type of the handler**. Any violation of this rule will + almost certainly result in unspecified behavior (in other words, it will break in spectacular ways). Exceptions + to this rule are the query methods ``isHolding()`` and ``isFinishing()`` + +To illustrate these concepts we create a small :class:`PushPullStage` that implements the ``map`` transformation. + +.. image:: ../images/stage_map.png + :align: center + :width: 300 + +Map calls ``ctx.push()`` from the ``onPush()`` handler and it also calls ``ctx.pull()`` form the ``onPull`` +handler resulting in the conceptual wiring above, and fully expressed in code below: + +.. includecode:: code/docs/stream/FlowStagesSpec.scala#one-to-one + +Map is a typical example of a one-to-one transformation of a stream. To demonstrate a many-to-one stage we will implement +filter. The conceptual wiring of ``Filter`` looks like this: + +.. image:: ../images/stage_filter.png + :align: center + :width: 300 + +As we see above, if the given predicate matches the current element we are propagating it downwards, otherwise +we return the "ball" to our upstream so that we get the new element. This is achieved by modifying the map +example by adding a conditional in the ``onPush`` handler and decide between a ``ctx.pull()`` or ``ctx.push()`` call +(and of course not having a mapping ``f`` function). + +.. includecode:: code/docs/stream/FlowStagesSpec.scala#many-to-one + +To complete the picture we define a one-to-many transformation as the next step. We chose a straightforward example stage +that emits every upstream element twice downstream. The conceptual wiring of this stage looks like this: + +.. image:: ../images/stage_doubler.png + :align: center + :width: 300 + +This is a stage that has state: the last element it has seen, and a flag ``oneLeft`` that indicates if we +have duplicated this last element already or not. Looking at the code below, the reader might notice that our ``onPull`` +method is more complex than it is demonstrated by the figure above. The reason for this is completion handling, which we +will explain a little bit later. For now it is enough to look at the ``if(!ctx.isFinishing)`` block which +corresponds to the logic we expect by looking at the conceptual picture. + +.. includecode:: code/docs/stream/FlowStagesSpec.scala#one-to-many + +Finally, to demonstrate all of the stages above, we put them together into a processing chain, which conceptually +would correspond to the following structure: + +.. image:: ../images/stage_chain.png + :align: center + :width: 650 + +In code this is only a few lines, using the ``transform`` method to inject our custom processing into a stream: + +.. includecode:: code/docs/stream/FlowStagesSpec.scala#stage-chain + +Completion handling +^^^^^^^^^^^^^^^^^^^ + +Completion handling usually (but not exclusively) comes into the picture when processing stages need to emit a few +more elements after their upstream source has been completed. We have seen an example of this in our ``Duplicator`` class +where the last element needs to be doubled even after the upstream neighbor stage has been completed. Since the +``onUpstreamFinish()`` handler expects a :class:`TerminationDirective` as the return type we are only allowed to call +``ctx.finish()``, ``ctx.fail()`` or ``ctx.absorbTermination()``. Since the first two of these available methods will +immediately terminate, our only option is ``absorbTermination()``. It is also clear from the return type of +``onUpstreamFinish`` that we cannot call ``ctx.push()`` but we need to emit elements somehow! The trick is that after +calling ``absorbTermination()`` the ``onPull()`` handler will be called eventually, and at the same time +``ctx.isFinishing`` will return true, indicating that ``ctx.pull()`` cannot be called anymore. Now we are free to +emit additional elementss and call ``ctx.finish()`` or ``ctx.pushAndFinish()`` eventually to finish processing. + +.. note:: + The reason for this slightly complex termination sequence is that the underlying ``onComplete`` signal of + Reactive Streams may arrive without any pending demand, i.e. without respecting backpressure. This means that + our push/pull structure that was illustrated in the figure of our custom processing chain does not + apply to termination. Unlike our neat model that is analogous to a ball that bounces back-and-forth in a + pipe (it bounces back on ``Filter``, ``Duplicator`` for example) cannot describe the termination signals. By calling + ``absorbTermination()`` the execution environment checks if the conceptual token was *above* the current stage at + that time (which means that it will never come back, so the environment immediately calls ``onPull``) or it was + *below* (which means that it will come back eventually, so the environment does not need to call anything yet). + + +Using PushStage +--------------- + +Many one-to-one and many-to-one transformations do not need to override the ``onPull()`` handler at all since all +they do is just propagate the pull upwards. For such transformations it is better to extend PushStage directly. For +example our ``Map`` and ``Filter`` would look like this: + +.. includecode:: code/docs/stream/FlowStagesSpec.scala#pushstage + +The reason to use ``PushStage`` is not just cosmetic: internal optimizations rely on the fact that the onPull method +only calls ``ctx.pull()`` and allow the environment do process elements faster than without this knowledge. By +extending ``PushStage`` the environment can be sure that ``onPull()`` was not overridden since it is ``final`` on +``PushStage``. + Using StatefulStage ------------------- -*TODO* +On top of ``PushPullStage`` which is the most elementary and low-level abstraction and ``PushStage`` that is a +convenience class that also informs the environment about possible optimizations ``StatefulStage`` is a new tool that +builds on ``PushPullStage`` directly, adding various convenience methods on top of it. It is possible to explicitly +maintain state-machine like states using its ``become()`` method to encapsulates states explicitly. There is also +a handy ``emit()`` method that simplifies emitting multiple values given as an iterator. To demonstrate this feature +we reimplemented ``Duplicator`` in terms of a ``StatefulStage``: + +.. includecode:: code/docs/stream/FlowStagesSpec.scala#doubler-stateful Using DetachedStage -------------------