simplify materialized value computation tree, fixes #20015
- also fixes materialized value sources for graphs that import zero or one graphs, with and without Fusing
This commit is contained in:
parent
b52c498638
commit
b255a19374
31 changed files with 582 additions and 279 deletions
|
|
@ -30,6 +30,8 @@ final class Flow[-In, +Out, +Mat](private[stream] override val module: Module)
|
|||
|
||||
override val shape: FlowShape[In, Out] = module.shape.asInstanceOf[FlowShape[In, Out]]
|
||||
|
||||
override def toString: String = s"Flow($shape, $module)"
|
||||
|
||||
override type Repr[+O] = Flow[In @uncheckedVariance, O, Mat @uncheckedVariance]
|
||||
override type ReprMat[+O, +M] = Flow[In @uncheckedVariance, O, M]
|
||||
|
||||
|
|
@ -42,8 +44,14 @@ final class Flow[-In, +Out, +Mat](private[stream] override val module: Module)
|
|||
|
||||
override def viaMat[T, Mat2, Mat3](flow: Graph[FlowShape[Out, T], Mat2])(combine: (Mat, Mat2) ⇒ Mat3): Flow[In, T, Mat3] =
|
||||
if (this.isIdentity) {
|
||||
Flow.fromGraph(flow.asInstanceOf[Graph[FlowShape[In, T], Mat2]])
|
||||
.mapMaterializedValue(combine(NotUsed.asInstanceOf[Mat], _))
|
||||
import Predef.Map.empty
|
||||
import StreamLayout.{ CompositeModule, Ignore, IgnorableMatValComp, Transform, Atomic, Combine }
|
||||
val m = flow.module
|
||||
val mat =
|
||||
if (combine == Keep.left) {
|
||||
if (IgnorableMatValComp(m)) Ignore else Transform(_ => NotUsed, Atomic(m))
|
||||
} else Combine(combine.asInstanceOf[(Any, Any) => Any], Ignore, Atomic(m))
|
||||
new Flow(CompositeModule(Set(m), m.shape, empty, empty, mat, Attributes.none))
|
||||
} else {
|
||||
val flowCopy = flow.module.carbonCopy
|
||||
new Flow(
|
||||
|
|
@ -86,11 +94,14 @@ final class Flow[-In, +Out, +Mat](private[stream] override val module: Module)
|
|||
* }}}
|
||||
* The `combine` function is used to compose the materialized values of this flow and that
|
||||
* Sink into the materialized value of the resulting Sink.
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def toMat[Mat2, Mat3](sink: Graph[SinkShape[Out], Mat2])(combine: (Mat, Mat2) ⇒ Mat3): Sink[In, Mat3] = {
|
||||
if (isIdentity)
|
||||
Sink.fromGraph(sink.asInstanceOf[Graph[SinkShape[In], Mat2]])
|
||||
.mapMaterializedValue(combine(().asInstanceOf[Mat], _))
|
||||
.mapMaterializedValue(combine(NotUsed.asInstanceOf[Mat], _))
|
||||
else {
|
||||
val sinkCopy = sink.module.carbonCopy
|
||||
new Sink(
|
||||
|
|
@ -132,6 +143,9 @@ final class Flow[-In, +Out, +Mat](private[stream] override val module: Module)
|
|||
* }}}
|
||||
* The `combine` function is used to compose the materialized values of this flow and that
|
||||
* Flow into the materialized value of the resulting Flow.
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def joinMat[Mat2, Mat3](flow: Graph[FlowShape[Out, In], Mat2])(combine: (Mat, Mat2) ⇒ Mat3): RunnableGraph[Mat3] = {
|
||||
val flowCopy = flow.module.carbonCopy
|
||||
|
|
@ -176,6 +190,9 @@ final class Flow[-In, +Out, +Mat](private[stream] override val module: Module)
|
|||
* }}}
|
||||
* The `combine` function is used to compose the materialized values of this flow and that
|
||||
* [[BidiFlow]] into the materialized value of the resulting [[Flow]].
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def joinMat[I2, O2, Mat2, M](bidi: Graph[BidiShape[Out, O2, I2, In], Mat2])(combine: (Mat, Mat2) ⇒ M): Flow[I2, O2, M] = {
|
||||
val copy = bidi.module.carbonCopy
|
||||
|
|
@ -261,8 +278,6 @@ final class Flow[-In, +Out, +Mat](private[stream] override val module: Module)
|
|||
|
||||
/** Converts this Scala DSL element to it's Java DSL counterpart. */
|
||||
def asJava: javadsl.Flow[In, Out, Mat] = new javadsl.Flow(this)
|
||||
|
||||
override def toString = s"""Flow(${module})"""
|
||||
}
|
||||
|
||||
object Flow {
|
||||
|
|
@ -410,23 +425,23 @@ trait FlowOps[+Out, +Mat] {
|
|||
def recover[T >: Out](pf: PartialFunction[Throwable, T]): Repr[T] = andThen(Recover(pf))
|
||||
|
||||
/**
|
||||
* RecoverWith allows to switch to alternative Source on flow failure. It will stay in effect after
|
||||
* a failure has been recovered so that each time there is a failure it is fed into the `pf` and a new
|
||||
* Source may be materialized.
|
||||
*
|
||||
* Since the underlying failure signal onError arrives out-of-band, it might jump over existing elements.
|
||||
* This stage can recover the failure signal, but not the skipped elements, which will be dropped.
|
||||
*
|
||||
* '''Emits when''' element is available from the upstream or upstream is failed and element is available
|
||||
* from alternative Source
|
||||
*
|
||||
* '''Backpressures when''' downstream backpressures
|
||||
*
|
||||
* '''Completes when''' upstream completes or upstream failed with exception pf can handle
|
||||
*
|
||||
* '''Cancels when''' downstream cancels
|
||||
*
|
||||
*/
|
||||
* RecoverWith allows to switch to alternative Source on flow failure. It will stay in effect after
|
||||
* a failure has been recovered so that each time there is a failure it is fed into the `pf` and a new
|
||||
* Source may be materialized.
|
||||
*
|
||||
* Since the underlying failure signal onError arrives out-of-band, it might jump over existing elements.
|
||||
* This stage can recover the failure signal, but not the skipped elements, which will be dropped.
|
||||
*
|
||||
* '''Emits when''' element is available from the upstream or upstream is failed and element is available
|
||||
* from alternative Source
|
||||
*
|
||||
* '''Backpressures when''' downstream backpressures
|
||||
*
|
||||
* '''Completes when''' upstream completes or upstream failed with exception pf can handle
|
||||
*
|
||||
* '''Cancels when''' downstream cancels
|
||||
*
|
||||
*/
|
||||
def recoverWith[T >: Out](pf: PartialFunction[Throwable, Graph[SourceShape[T], NotUsed]]): Repr[T] =
|
||||
via(new RecoverWith(pf))
|
||||
|
||||
|
|
@ -466,27 +481,27 @@ trait FlowOps[+Out, +Mat] {
|
|||
def mapConcat[T](f: Out ⇒ immutable.Iterable[T]): Repr[T] = statefulMapConcat(() => f)
|
||||
|
||||
/**
|
||||
* Transform each input element into an `Iterable` of output elements that is
|
||||
* then flattened into the output stream. The transformation is meant to be stateful,
|
||||
* which is enabled by creating the transformation function anew for every materialization —
|
||||
* the returned function will typically close over mutable objects to store state between
|
||||
* invocations. For the stateless variant see [[FlowOps.mapConcat]].
|
||||
*
|
||||
* The returned `Iterable` MUST NOT contain `null` values,
|
||||
* as they are illegal as stream elements - according to the Reactive Streams specification.
|
||||
*
|
||||
* '''Emits when''' the mapping function returns an element or there are still remaining elements
|
||||
* from the previously calculated collection
|
||||
*
|
||||
* '''Backpressures when''' downstream backpressures or there are still remaining elements from the
|
||||
* previously calculated collection
|
||||
*
|
||||
* '''Completes when''' upstream completes and all remaining elements has been emitted
|
||||
*
|
||||
* '''Cancels when''' downstream cancels
|
||||
*
|
||||
* See also [[FlowOps.mapConcat]]
|
||||
*/
|
||||
* Transform each input element into an `Iterable` of output elements that is
|
||||
* then flattened into the output stream. The transformation is meant to be stateful,
|
||||
* which is enabled by creating the transformation function anew for every materialization —
|
||||
* the returned function will typically close over mutable objects to store state between
|
||||
* invocations. For the stateless variant see [[FlowOps.mapConcat]].
|
||||
*
|
||||
* The returned `Iterable` MUST NOT contain `null` values,
|
||||
* as they are illegal as stream elements - according to the Reactive Streams specification.
|
||||
*
|
||||
* '''Emits when''' the mapping function returns an element or there are still remaining elements
|
||||
* from the previously calculated collection
|
||||
*
|
||||
* '''Backpressures when''' downstream backpressures or there are still remaining elements from the
|
||||
* previously calculated collection
|
||||
*
|
||||
* '''Completes when''' upstream completes and all remaining elements has been emitted
|
||||
*
|
||||
* '''Cancels when''' downstream cancels
|
||||
*
|
||||
* See also [[FlowOps.mapConcat]]
|
||||
*/
|
||||
def statefulMapConcat[T](f: () ⇒ Out ⇒ immutable.Iterable[T]): Repr[T] =
|
||||
via(new StatefulMapConcat(f))
|
||||
|
||||
|
|
@ -1813,6 +1828,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* }}}
|
||||
* The `combine` function is used to compose the materialized values of this flow and that
|
||||
* flow into the materialized value of the resulting Flow.
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def viaMat[T, Mat2, Mat3](flow: Graph[FlowShape[Out, T], Mat2])(combine: (Mat, Mat2) ⇒ Mat3): ReprMat[T, Mat3]
|
||||
|
||||
|
|
@ -1831,6 +1849,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* }}}
|
||||
* The `combine` function is used to compose the materialized values of this flow and that
|
||||
* Sink into the materialized value of the resulting Sink.
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def toMat[Mat2, Mat3](sink: Graph[SinkShape[Out], Mat2])(combine: (Mat, Mat2) ⇒ Mat3): ClosedMat[Mat3]
|
||||
|
||||
|
|
@ -1838,6 +1859,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* Combine the elements of current flow and the given [[Source]] into a stream of tuples.
|
||||
*
|
||||
* @see [[#zip]].
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def zipMat[U, Mat2, Mat3](that: Graph[SourceShape[U], Mat2])(matF: (Mat, Mat2) ⇒ Mat3): ReprMat[(Out, U), Mat3] =
|
||||
viaMat(zipGraph(that))(matF)
|
||||
|
|
@ -1847,6 +1871,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* into a stream of combined elements using a combiner function.
|
||||
*
|
||||
* @see [[#zipWith]].
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def zipWithMat[Out2, Out3, Mat2, Mat3](that: Graph[SourceShape[Out2], Mat2])(combine: (Out, Out2) ⇒ Out3)(matF: (Mat, Mat2) ⇒ Mat3): ReprMat[Out3, Mat3] =
|
||||
viaMat(zipWithGraph(that)(combine))(matF)
|
||||
|
|
@ -1856,6 +1883,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* picking randomly when several elements ready.
|
||||
*
|
||||
* @see [[#merge]].
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def mergeMat[U >: Out, Mat2, Mat3](that: Graph[SourceShape[U], Mat2], eagerComplete: Boolean = false)(matF: (Mat, Mat2) ⇒ Mat3): ReprMat[U, Mat3] =
|
||||
viaMat(mergeGraph(that, eagerComplete))(matF)
|
||||
|
|
@ -1870,6 +1900,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* If it gets error from one of upstreams - stream completes with failure.
|
||||
*
|
||||
* @see [[#interleave]].
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def interleaveMat[U >: Out, Mat2, Mat3](that: Graph[SourceShape[U], Mat2], request: Int)(matF: (Mat, Mat2) ⇒ Mat3): ReprMat[U, Mat3] =
|
||||
viaMat(interleaveGraph(that, request))(matF)
|
||||
|
|
@ -1882,6 +1915,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* does not complete).
|
||||
*
|
||||
* @see [[#mergeSorted]].
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def mergeSortedMat[U >: Out, Mat2, Mat3](that: Graph[SourceShape[U], Mat2])(matF: (Mat, Mat2) ⇒ Mat3)(implicit ord: Ordering[U]): ReprMat[U, Mat3] =
|
||||
viaMat(mergeSortedGraph(that))(matF)
|
||||
|
|
@ -1897,6 +1933,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* If this [[Flow]] gets upstream error - no elements from the given [[Source]] will be pulled.
|
||||
*
|
||||
* @see [[#concat]].
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def concatMat[U >: Out, Mat2, Mat3](that: Graph[SourceShape[U], Mat2])(matF: (Mat, Mat2) ⇒ Mat3): ReprMat[U, Mat3] =
|
||||
viaMat(concatGraph(that))(matF)
|
||||
|
|
@ -1912,6 +1951,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* If the given [[Source]] gets upstream error - no elements from this [[Flow]] will be pulled.
|
||||
*
|
||||
* @see [[#prepend]].
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def prependMat[U >: Out, Mat2, Mat3](that: Graph[SourceShape[U], Mat2])(matF: (Mat, Mat2) ⇒ Mat3): ReprMat[U, Mat3] =
|
||||
viaMat(prependGraph(that))(matF)
|
||||
|
|
@ -1921,6 +1963,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* through will also be sent to the [[Sink]].
|
||||
*
|
||||
* @see [[#alsoTo]]
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def alsoToMat[Mat2, Mat3](that: Graph[SinkShape[Out], Mat2])(matF: (Mat, Mat2) ⇒ Mat3): ReprMat[Out, Mat3] =
|
||||
viaMat(alsoToGraph(that))(matF)
|
||||
|
|
@ -1930,6 +1975,9 @@ trait FlowOpsMat[+Out, +Mat] extends FlowOps[Out, Mat] {
|
|||
* The Future completes with success when received complete message from upstream or cancel
|
||||
* from downstream. It fails with the same error when received error message from
|
||||
* downstream.
|
||||
*
|
||||
* It is recommended to use the internally optimized `Keep.left` and `Keep.right` combiners
|
||||
* where appropriate instead of manually writing functions that pass through one of the values.
|
||||
*/
|
||||
def watchTermination[Mat2]()(matF: (Mat, Future[Done]) ⇒ Mat2): ReprMat[Out, Mat2] =
|
||||
viaMat(GraphStages.terminationWatcher)(matF)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue