diff --git a/akka-docs-dev/rst/java/stream-graphs.rst b/akka-docs-dev/rst/java/stream-graphs.rst index 31b0f09e0c..3d2cb93c00 100644 --- a/akka-docs-dev/rst/java/stream-graphs.rst +++ b/akka-docs-dev/rst/java/stream-graphs.rst @@ -64,10 +64,10 @@ The same is true of all flow pieces—sources, sinks, and flows—once they are This means that you can safely re-use one given Flow in multiple places in a processing graph. We have seen examples of such re-use already above: the merge and broadcast junctions were imported -into the graph using ``builder.graph(...)``, an operation that will make a copy of the blueprint that +into the graph using ``builder.add(...)``, an operation that will make a copy of the blueprint that is passed to it and return the inlets and outlets of the resulting copy so that they can be wired up. Another alternative is to pass existing graphs—of any shape—into the factory method that produces a -new graph. The difference between these approaches is that importing using ``b.graph(...)`` ignores the +new graph. The difference between these approaches is that importing using ``builder.add(...)`` ignores the materialized value of the imported graph while importing via the factory method allows its inclusion; for more details see :ref:`stream-materialization-scala`. @@ -85,9 +85,8 @@ Constructing and combining Partial Flow Graphs Sometimes it is not possible (or needed) to construct the entire computation graph in one place, but instead construct all of its different phases in different places and in the end connect them all into a complete graph and run it. -This can be achieved using ``FlowGraph.create()`` instead of -``FlowGraph.runnable()``, which will return a ``Graph`` instead of a -``RunnableGraph``. The reason of representing it as a different type is that a +This can be achieved by using the returned :class:`Graph` from ``FlowGraph.create()`` rather than +passing it to ``RunnableGraph.fromGraph()`` to wrap it in a :class:`RunnableGraph`.The reason of representing it as a different type is that a :class:`RunnableGraph` requires all ports to be connected, and if they are not it will throw an exception at construction time, which helps to avoid simple wiring errors while working with graphs. A partial flow graph however allows @@ -102,11 +101,11 @@ the greatest int value of each zipped triple. We'll want to expose 3 input ports As you can see, first we construct the partial graph that describes how to compute the maximum of two input streams, then we reuse that twice while constructing the partial graph that extends this to three input streams, -then we import it (all of its nodes and connections) explicitly to the :class:`FlowGraph` instance in which all +then we import it (all of its nodes and connections) explicitly into the last graph in which all the undefined elements are rewired to real sources and sinks. The graph can then be run and yields the expected result. .. warning:: - Please note that a :class:`FlowGraph` is not able to provide compile time type-safety about whether or not all + Please note that :class:`FlowGraph` is not able to provide compile time type-safety about whether or not all elements have been properly connected—this validation is performed as a runtime check during the graph's instantiation. A partial flow graph also verifies that all ports are either connected or part of the returned :class:`Shape`. @@ -116,28 +115,31 @@ the undefined elements are rewired to real sources and sinks. The graph can then Constructing Sources, Sinks and Flows from Partial Graphs --------------------------------------------------------- -Instead of treating a :class:`PartialFlowGraph` as simply a collection of flows and junctions which may not yet all be +Instead of treating a ``Graph`` as simply a collection of flows and junctions which may not yet all be connected it is sometimes useful to expose such a complex graph as a simpler structure, such as a :class:`Source`, :class:`Sink` or :class:`Flow`. In fact, these concepts can be easily expressed as special cases of a partially connected graph: -* :class:`Source` is a partial flow graph with *exactly one* output, that is it returns a :class:`SourceShape`. -* :class:`Sink` is a partial flow graph with *exactly one* input, that is it returns a :class:`SinkShape`. -* :class:`Flow` is a partial flow graph with *exactly one* input and *exactly one* output, that is it returns a :class:`FlowShape`. +* :class:`Source` is a partial graph with *exactly one* output, that is it returns a :class:`SourceShape`. +* :class:`Sink` is a partial graph with *exactly one* input, that is it returns a :class:`SinkShape`. +* :class:`Flow` is a partial graph with *exactly one* input and *exactly one* output, that is it returns a :class:`FlowShape`. Being able to hide complex graphs inside of simple elements such as Sink / Source / Flow enables you to easily create one complex element and from there on treat it as simple compound stage for linear computations. -In order to create a Source from a partial flow graph ``Source`` provides a special apply method that takes a function -that must return an :class:`Outlet`. This unconnected sink will become “the sink that must be attached before this Source -can run”. Refer to the example below, in which we create a Source that zips together two numbers, to see this graph +In order to create a Source from a graph the method ``Source.fromGraph`` is used, to use it we must have a +``Graph`` with a ``SourceShape``. This is constructed using ``FlowGraph.create`` and providing building a ``SourceShape`` +graph. The single outlet must be provided to the ``SourceShape.of`` method and will become “the sink that must +be attached before this Source can run”. + +Refer to the example below, in which we create a Source that zips together two numbers, to see this graph construction in action: .. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamPartialFlowGraphDocTest.java#source-from-partial-flow-graph -Similarly the same can be done for a ``Sink``, in which case the returned value must be an ``Inlet``. -For defining a ``Flow`` we need to expose both an undefined source and sink: +Similarly the same can be done for a ``Sink`` using ``SinkShape.of`` in which case the provided value must be an +``Inlet``. For defining a ``Flow`` we need to expose both an undefined source and sink: .. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamPartialFlowGraphDocTest.java#flow-from-partial-flow-graph diff --git a/akka-docs-dev/rst/java/stream-quickstart.rst b/akka-docs-dev/rst/java/stream-quickstart.rst index 764569f024..63f5d198ab 100644 --- a/akka-docs-dev/rst/java/stream-quickstart.rst +++ b/akka-docs-dev/rst/java/stream-quickstart.rst @@ -103,27 +103,28 @@ Elements that can be used to form such "fan-out" (or "fan-in") structures are re One of these that we'll be using in this example is called :class:`Broadcast`, and it simply emits elements from its input port to all of its output ports. -Akka Streams intentionally separate the linear stream structures (Flows) from the non-linear, branching ones (FlowGraphs) +Akka Streams intentionally separate the linear stream structures (Flows) from the non-linear, branching ones (Graphs) in order to offer the most convenient API for both of these cases. Graphs can express arbitrarily complex stream setups -at the expense of not reading as familiarly as collection transformations. +at the expense of not reading as familiarly as collection transformations. - -A graph can be either ``closed`` which is also known as a "*fully connected graph*", or ``partial`` which can be seen as -a *partial graph* (a graph with some unconnected ports), thus being a generalisation of the Flow concept, where ``Flow`` -is simply a partial graph with one unconnected input and one unconnected output. Concepts around composing and nesting -graphs in large structures are explained explained in detail in :ref:`composition-java`. - -It is also possible to wrap complex computation graphs as Flows, Sinks or Sources, which will be explained in -detail in :ref:`constructing-sources-sinks-flows-from-partial-graphs-java`. FlowGraphs are constructed like this: +Graphs are constructed using :class:`FlowGraph` like this: .. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#flow-graph-broadcast -As you can see, we use graph builder ``b`` to construct the graph using ``UniformFanOutShape`` and ``Flow``s. Once we have the -FlowGraph as a result of ``runnable()`` method *it is immutable, thread-safe, and freely shareable*. A graph can be ``run()`` directly - -assuming all ports (sinks/sources) within a flow have been connected properly. It is possible also to construct several :class:`PartialFlowGraph`s and -and then combine them into one fully connected graph. This will be covered in detail in :ref:`partial-flow-graph-java`. +As you can see, we use graph builder ``b`` to construct the graph using ``UniformFanOutShape`` and ``Flow`` s. + +``FlowGraph.create`` returns a :class:`Graph`, in this example a ``Graph`` where +:class:`ClosedShape` means that it is *a fully connected graph* or "closed" - there are no unconnected inputs or outputs. +Since it is closed it is possible to transform the graph into a :class:`RunnableGraph` using ``RunnableGraph.fromGraph``. +The runnable graph can then be ``run()`` to materialize a stream out of it. + +Both :class:`Graph` and :class:`RunnableGraph` are *immutable, thread-safe, and freely shareable*. + +A graph can also have one of several other shapes, with one or more unconnected ports. Having unconnected ports +expresses a grapth that is a *partial graph*. Concepts around composing and nesting graphs in large structures are +explained explained in detail in :ref:`composition-java`. It is also possible to wrap complex computation graphs +as Flows, Sinks or Sources, which will be explained in detail in :ref:`partial-flow-graph-java`. -As all Akka Streams elements, :class:`Broadcast` will properly propagate back-pressure to its upstream element. Back-pressure in action ----------------------- diff --git a/akka-docs-dev/rst/scala/stream-graphs.rst b/akka-docs-dev/rst/scala/stream-graphs.rst index 95e665e53d..4be72c9bba 100644 --- a/akka-docs-dev/rst/scala/stream-graphs.rst +++ b/akka-docs-dev/rst/scala/stream-graphs.rst @@ -72,7 +72,7 @@ We have seen examples of such re-use already above: the merge and broadcast junc into the graph using ``builder.add(...)``, an operation that will make a copy of the blueprint that is passed to it and return the inlets and outlets of the resulting copy so that they can be wired up. Another alternative is to pass existing graphs—of any shape—into the factory method that produces a -new graph. The difference between these approaches is that importing using ``b.add(...)`` ignores the +new graph. The difference between these approaches is that importing using ``builder.add(...)`` ignores the materialized value of the imported graph while importing via the factory method allows its inclusion; for more details see :ref:`stream-materialization-scala`. @@ -90,10 +90,10 @@ Constructing and combining Partial Flow Graphs Sometimes it is not possible (or needed) to construct the entire computation graph in one place, but instead construct all of its different phases in different places and in the end connect them all into a complete graph and run it. -This can be achieved using ``FlowGraph.partial`` instead of -``FlowGraph.closed``, which will return a ``Graph`` instead of a -``RunnableGraph``. The reason of representing it as a different type is that a -:class:`RunnableGraph` requires all ports to be connected, and if they are not +This can be achieved by returning a different ``Shape`` than ``ClosedShape``, for example ``FlowShape(in, out)``, from the +function given to ``FlowGraph.create``. See :ref:`predefined_shapes`) for a list of such predefined shapes. + +Making a ``Graph`` a :class:`RunnableGraph` requires all ports to be connected, and if they are not it will throw an exception at construction time, which helps to avoid simple wiring errors while working with graphs. A partial flow graph however allows you to return the set of yet to be connected ports from the code block that @@ -112,7 +112,7 @@ the undefined elements are rewired to real sources and sinks. The graph can then .. warning:: - Please note that a :class:`FlowGraph` is not able to provide compile time type-safety about whether or not all + Please note that :class:`FlowGraph` is not able to provide compile time type-safety about whether or not all elements have been properly connected—this validation is performed as a runtime check during the graph's instantiation. A partial flow graph also verifies that all ports are either connected or part of the returned :class:`Shape`. @@ -122,35 +122,38 @@ the undefined elements are rewired to real sources and sinks. The graph can then Constructing Sources, Sinks and Flows from Partial Graphs --------------------------------------------------------- -Instead of treating a partial flow graph as simply a collection of flows and junctions which may not yet all be +Instead of treating a partial graph as simply a collection of flows and junctions which may not yet all be connected it is sometimes useful to expose such a complex graph as a simpler structure, such as a :class:`Source`, :class:`Sink` or :class:`Flow`. In fact, these concepts can be easily expressed as special cases of a partially connected graph: -* :class:`Source` is a partial flow graph with *exactly one* output, that is it returns a :class:`SourceShape`. -* :class:`Sink` is a partial flow graph with *exactly one* input, that is it returns a :class:`SinkShape`. -* :class:`Flow` is a partial flow graph with *exactly one* input and *exactly one* output, that is it returns a :class:`FlowShape`. +* :class:`Source` is a partial graph with *exactly one* output, that is it returns a :class:`SourceShape`. +* :class:`Sink` is a partial graph with *exactly one* input, that is it returns a :class:`SinkShape`. +* :class:`Flow` is a partial graph with *exactly one* input and *exactly one* output, that is it returns a :class:`FlowShape`. Being able to hide complex graphs inside of simple elements such as Sink / Source / Flow enables you to easily create one complex element and from there on treat it as simple compound stage for linear computations. -In order to create a Source from a partial flow graph ``Source`` provides a special apply method that takes a function -that must return an :class:`Outlet[T]`. This unconnected sink will become “the sink that must be attached before this Source -can run”. Refer to the example below, in which we create a Source that zips together two numbers, to see this graph +In order to create a Source from a graph the method ``Source.fromGraph`` is used, to use it we must have a +``Graph[SourceShape, T]``. This is constructed using ``FlowGraph.create`` and returning a ``SourceShape`` +from the function passed in . The single outlet must be provided to the ``SourceShape.of`` method and will become +“the sink that must be attached before this Source can run”. + +Refer to the example below, in which we create a Source that zips together two numbers, to see this graph construction in action: .. includecode:: code/docs/stream/StreamPartialFlowGraphDocSpec.scala#source-from-partial-flow-graph -Similarly the same can be done for a ``Sink[T]``, in which case the returned value must be an ``Inlet[T]``. -For defining a ``Flow[T]`` we need to expose both an inlet and an outlet: +Similarly the same can be done for a ``Sink[T]``, using ``SinkShape.of`` in which case the provided value +must be an ``Inlet[T]``. For defining a ``Flow[T]`` we need to expose both an inlet and an outlet: .. includecode:: code/docs/stream/StreamPartialFlowGraphDocSpec.scala#flow-from-partial-flow-graph Combining Sources and Sinks with simplified API ----------------------------------------------- -There is simplified API you can use to combine sources and sinks with junctions like: ``Broadcast[T]``, ``Balance[T]``, +There is a simplified API you can use to combine sources and sinks with junctions like: ``Broadcast[T]``, ``Balance[T]``, ``Merge[In]`` and ``Concat[A]`` without the need for using the Graph DSL. The combine method takes care of constructing the necessary graph underneath. In following example we combine two sources into one (fan-in): diff --git a/akka-docs-dev/rst/scala/stream-quickstart.rst b/akka-docs-dev/rst/scala/stream-quickstart.rst index a9f167d850..85651f9036 100644 --- a/akka-docs-dev/rst/scala/stream-quickstart.rst +++ b/akka-docs-dev/rst/scala/stream-quickstart.rst @@ -99,32 +99,31 @@ Elements that can be used to form such "fan-out" (or "fan-in") structures are re One of these that we'll be using in this example is called :class:`Broadcast`, and it simply emits elements from its input port to all of its output ports. -Akka Streams intentionally separate the linear stream structures (Flows) from the non-linear, branching ones (FlowGraphs) +Akka Streams intentionally separate the linear stream structures (Flows) from the non-linear, branching ones (Graphs) in order to offer the most convenient API for both of these cases. Graphs can express arbitrarily complex stream setups at the expense of not reading as familiarly as collection transformations. -A graph can be either ``closed`` which is also known as a "*fully connected graph*", or ``partial`` which can be seen as -a *partial graph* (a graph with some unconnected ports), thus being a generalisation of the Flow concept, where ``Flow`` -is simply a partial graph with one unconnected input and one unconnected output. Concepts around composing and nesting -graphs in large structures are explained explained in detail in :ref:`composition-scala`. - -It is also possible to wrap complex computation -graphs as Flows, Sinks or Sources, which will be explained in detail in :ref:`constructing-sources-sinks-flows-from-partial-graphs-scala`. -FlowGraphs are constructed like this: +Graphs are constructed using :class:`FlowGraph` like this: .. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#flow-graph-broadcast -.. note:: - The ``~>`` (read as "edge", "via" or "to") operator is only available if ``FlowGraph.Implicits._`` are imported. - Without this import you can still construct graphs using the ``builder.addEdge(from,[through,]to)`` method. +As you can see, inside the :class:`FlowGraph` we use an implicit graph builder ``b`` to mutably construct the graph +using the ``~>`` "edge operator" (also read as "connect" or "via" or "to"). The operator is provided implicitly +by importing ``FlowGraph.Implicits._``. -As you can see, inside the :class:`FlowGraph` we use an implicit graph builder to mutably construct the graph -using the ``~>`` "edge operator" (also read as "connect" or "via" or "to"). Once we have the FlowGraph in the value ``g`` -*it is immutable, thread-safe, and freely shareable*. A graph can be ``run()`` directly - assuming all -ports (sinks/sources) within a flow have been connected properly. It is possible to construct partial graphs -where this is not required but this will be covered in detail in :ref:`partial-flow-graph-scala`. +``FlowGraph.create`` returns a :class:`Graph`, in this example a :class:`Graph[ClosedShape, Unit]` where +:class:`ClosedShape` means that it is *a fully connected graph* or "closed" - there are no unconnected inputs or outputs. +Since it is closed it is possible to transform the graph into a :class:`RunnableGraph` using ``RunnableGraph.fromGraph``. +The runnable graph can then be ``run()`` to materialize a stream out of it. + +Both :class:`Graph` and :class:`RunnableGraph` are *immutable, thread-safe, and freely shareable*. + +A graph can also have one of several other shapes, with one or more unconnected ports. Having unconnected ports +expresses a grapth that is a *partial graph*. Concepts around composing and nesting graphs in large structures are +explained explained in detail in :ref:`composition-scala`. It is also possible to wrap complex computation graphs +as Flows, Sinks or Sources, which will be explained in detail in +:ref:`constructing-sources-sinks-flows-from-partial-graphs-scala`. -As all Akka Streams elements, :class:`Broadcast` will properly propagate back-pressure to its upstream element. Back-pressure in action -----------------------