Align lazy and future operators #26446

This commit is contained in:
Johan Andrén 2019-10-16 17:02:12 +02:00 committed by GitHub
parent 4a72985e48
commit 74adecb4e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
59 changed files with 2091 additions and 384 deletions

View file

@ -717,3 +717,78 @@ This also means that custom `GraphStage` implementations should be changed to pa
cancellation cause when downstream cancels by implementing the `OutHandler.onDownstreamFinish` signature
taking a `cause` parameter and calling `cancelStage(cause)` to pass the cause upstream. The old zero-argument
`onDownstreamFinish` method has been deprecated.
### Lazy and async stream operator changes
The operators that provide support for lazy and @scala[`Future`]@java[`CompletionStage`] stream construction were revised
to be more consistent.
The materialized value is now no longer wrapped in an @scala[`Option`]@java[`Optional`], instead the @scala[`Future`]@java[`CompletionStage`]
is failed with a `akka.stream.NeverMaterializedException` in the cases that would previously lead to @scala[`None`]@java[an empty `Optional`]
A deferred creation of the stream based on the initial element like how the deprecated `lazyInit` worked can be achieved by combining
@scala[`future(Flow|Sink)`] @java[`completionStage(Flow|Sink)`] with `prefixAndTail`. See example in @scala[@ref:[futureFlow](../stream/operators/Flow/futureFlow.md)]
@java[@ref:[completionStageFlow](../stream/operators/Flow/completionStageFlow.md)].
#### javadsl.Flow
| old | new |
------------------------|----------------
| lazyInit | @ref:[lazyCompletionStageFlow](../stream/operators/Flow/lazyCompletionStageFlow.md) in combination with `prefixAndTail(1)` |
| lazyInitAsync | @ref:[lazyCompletionStageFlow](../stream/operators/Flow/lazyCompletionStageFlow.md) |
| | @ref:[completionStageFlow](../stream/operators/Flow/completionStageFlow.md) |
| | @ref:[lazyFlow](../stream/operators/Flow/lazyFlow.md) |
### javadsl.Sink
| old | new |
------------------------|----------------
| lazyInit | @ref:[lazyCompletionStageSink](../stream/operators/Sink/lazyCompletionStageSink.md) in combination with `Flow.prefixAndTail(1)` |
| lazyInitAsync | @ref:[lazyCompletionStageSink](../stream/operators/Sink/lazyCompletionStageSink.md) |
| | @ref:[completionStageSink](../stream/operators/Sink/completionStageSink.md) |
| | @ref:[lazySink](../stream/operators/Sink/lazySink.md) |
### javadsl.Source
| old | new |
--------------------------|----------------
| fromFuture | @ref:[future](../stream/operators/Source/future.md) |
| fromCompletionStage | @ref:[completionStage](../stream/operators/Source/completionStage.md) |
| fromFutureSource | @ref:[futureSource](../stream/operators/Source/futureSource.md) |
| fromSourceCompletionStage | @ref:[completionStageSource](../stream/operators/Source/completionStageSource.md) |
| lazily | @ref:[lazySource](../stream/operators/Source/lazySource.md) |
| lazilyAsync | @ref:[lazyCompletionStage](../stream/operators/Source/lazyCompletionStage.md) |
| | @ref:[lazySingle](../stream/operators/Source/lazySingle.md) |
| | @ref:[lazyCompletionStageSource](../stream/operators/Source/lazyCompletionStageSource.md) |
### scaladsl.Flow
| old | new |
--------------------------|----------------
| lazyInit | @ref:[lazyFutureFlow](../stream/operators/Flow/lazyFutureFlow.md) |
| lazyInitAsync | @ref:[lazyFutureFlow](../stream/operators/Flow/lazyFutureFlow.md) |
| | @ref:[futureFlow](../stream/operators/Flow/futureFlow.md) |
| | @ref:[lazyFlow](../stream/operators/Flow/lazyFlow.md) |
### scaladsl.Sink
| old | new |
------------------------|----------------
| lazyInit | @ref:[lazyFutureSink](../stream/operators/Sink/lazyFutureSink.md) in combination with `Flow.prefixAndTail(1)` |
| lazyInitAsync | @ref:[lazyFutureSink](../stream/operators/Sink/lazyFutureSink.md) |
| | @ref:[futureSink](../stream/operators/Sink/futureSink.md) |
| | @ref:[lazySink](../stream/operators/Sink/lazySink.md) |
### scaladsl.Source
| old | new |
--------------------------|----------------
| fromFuture | @ref:[future](../stream/operators/Source/future.md) |
| fromCompletionStage | @ref:[completionStage](../stream/operators/Source/completionStage.md) |
| fromFutureSource | @ref:[futureSource](../stream/operators/Source/futureSource.md) |
| fromSourceCompletionStage | |
| lazily | @ref:[lazySource](../stream/operators/Source/lazySource.md) |
| lazilyAsync | @ref:[lazyFuture](../stream/operators/Source/lazyFuture.md) |
| | @ref:[lazySingle](../stream/operators/Source/lazySingle.md) |
| | @ref:[lazyFutureSource](../stream/operators/Source/lazyFutureSource.md) |

View file

@ -0,0 +1,42 @@
# Flow.completionStageFlow
Streams the elements through the given future flow once it successfully completes.
@ref[Simple operators](../index.md#simple-operators)
@@@div { .group-scala }
## Signature
@@signature [Flow.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Flow.scala) { #futureFlow }
@@@
## Description
Streams the elements through the given flow once the `CompletionStage` successfully completes.
If the future fails the stream is failed.
## Examples
A deferred creation of the stream based on the initial element by combining `completionStageFlow`
with `prefixAndTail` like so:
Scala
: @@snip [FutureFlow.java](/akka-docs/src/test/java/jdocs/stream/operators/flow/FutureFlow.java) { #base-on-first-element }
## Reactive Streams semantics
@@@div { .callout }
**emits** when the internal flow is successfully created and it emits
**backpressures** when the internal flow is successfully created and it backpressures
**completes** when upstream completes and all elements have been emitted from the internal flow
**completes** when upstream completes and all futures have been completed and all elements have been emitted
@@@

View file

@ -0,0 +1,43 @@
# Flow.futureFlow
Streams the elements through the given future flow once it successfully completes.
@ref[Simple operators](../index.md#simple-operators)
@@@div { .group-scala }
## Signature
@@signature [Flow.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Flow.scala) { #futureFlow }
@@@
## Description
Streams the elements through the given future flow once it successfully completes.
If the future fails the stream is failed.
## Examples
A deferred creation of the stream based on the initial element can be achieved by combining `futureFlow`
with `prefixAndTail` like so:
Scala
: @@snip [FutureFlow.scala](/akka-docs/src/test/scala/docs/stream/operators/flow/FutureFlow.scala) { #base-on-first-element }
## Reactive Streams semantics
@@@div { .callout }
**emits** when the internal flow is successfully created and it emits
**backpressures** when the internal flow is successfully created and it backpressures
**completes** when upstream completes and all elements have been emitted from the internal flow
**completes** when upstream completes and all futures have been completed and all elements have been emitted
@@@

View file

@ -0,0 +1,35 @@
# Flow.lazyCompletionStageFlow
Defers creation and materialization of a `Flow` until there is a first element.
@ref[Simple operators](../index.md#simple-operators)
## Description
When the first element comes from upstream the actual `CompletionStage<Flow>` is created and when that completes it is materialized
and inserted in the stream.
The internal `Flow` will not be created if there are no elements on completion or failure of up or downstream.
The materialized value of the `Flow` will be the materialized value of the created internal flow if it is materialized
and failed with a `akka.stream.NeverMaterializedException` if the stream fails or completes without the flow being materialized.
See also @ref:[lazyFlow](lazyFlow.md).
Can be combined with `prefixAndTail(1)` to base the flow construction on the initial element triggering creation.
See @ref:[lazyFlow](lazyFlow.md) for sample.
## Reactive Streams semantics
@@@div { .callout }
**emits** when the internal flow is successfully created and it emits
**backpressures** when the internal flow is successfully created and it backpressures
**completes** when upstream completes and all elements have been emitted from the internal flow
**completes** when upstream completes and all futures have been completed and all elements have been emitted
@@@

View file

@ -0,0 +1,36 @@
# Flow.lazyFlow
Defers creation and materialization of a `Flow` until there is a first element.
@ref[Simple operators](../index.md#simple-operators)
@@@div { .group-scala }
## Signature
@@signature [Flow.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Flow.scala) { #lazyFlow }
@@@
## Description
When the first element comes from upstream the actual `Flow` is created and materialized.
The internal `Flow` will not be created if there are no elements on completion or failure of up or downstream.
The materialized value of the `Flow` will be the materialized value of the created internal flow if it is materialized
and failed with a `akka.stream.NeverMaterializedException` if the stream fails or completes without the flow being materialized.
## Reactive Streams semantics
@@@div { .callout }
**emits** when the internal flow is successfully created and it emits
**backpressures** when the internal flow is successfully created and it backpressures
**completes** when upstream completes and all elements have been emitted from the internal flow
**completes** when upstream completes and all futures have been completed and all elements have been emitted
@@@

View file

@ -0,0 +1,42 @@
# Flow.lazyFutureFlow
Defers creation and materialization of a `Flow` until there is a first element.
@ref[Simple operators](../index.md#simple-operators)
@@@div { .group-scala }
## Signature
@@signature [Flow.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Flow.scala) { #lazyFlow }
@@@
## Description
When the first element comes from upstream the actual `Future[Flow]` is created and when that completes it is materialized
and inserted in the stream.
The internal `Flow` will not be created if there are no elements on completion or failure of up or downstream.
The materialized value of the `Flow` will be the materialized value of the created internal flow if it is materialized
and failed with a `akka.stream.NeverMaterializedException` if the stream fails or completes without the flow being materialized.
See also @ref:[lazyFlow](lazyFlow.md).
Can be combined with `prefixAndTail(1)` to base the flow construction on the initial element triggering creation.
See @ref:[lazyFlow](lazyFlow.md) for sample.
## Reactive Streams semantics
@@@div { .callout }
**emits** when the internal flow is successfully created and it emits
**backpressures** when the internal flow is successfully created and it backpressures
**completes** when upstream completes and all elements have been emitted from the internal flow
**completes** when upstream completes and all futures have been completed and all elements have been emitted
@@@

View file

@ -1,6 +1,6 @@
# Flow.lazyInitAsync
Creates a real `Flow` upon receiving the first element by calling relevant `flowFactory` given as an argument.
`lazyInitAsync` has been deprecated in 2.6.0 use `Flow.lazyFutureFlow` in combination with `prefixAndTail` instead.
@ref[Simple operators](../index.md#simple-operators)
@ -14,17 +14,9 @@ Creates a real `Flow` upon receiving the first element by calling relevant `flow
## Description
Creates a real `Flow` upon receiving the first element by calling relevant `flowFactory` given as an argument.
Internal `Flow` will not be created if there are no elements, because of completion or error.
The materialized value of the `Flow` will be the materialized value of the created internal flow.
`fromCompletionStage` has been deprecated in 2.6.0 use @ref:[lazyFutureFlow](lazyFutureFlow.md) in combination with `prefixAndTail` instead.
The materialized value of the `Flow` is a @scala[`Future[Option[M]]`]@java[`CompletionStage<Optional<M>>`] that is
completed with @scala[`Some(mat)`]@java[`Optional.of(mat)`] when the internal flow gets materialized or with @scala[`None`]
@java[an empty optional] when there where no elements. If the flow materialization (including the call of the `flowFactory`)
fails then the future is completed with a failure.
Adheres to the @scala[@scaladoc[`ActorAttributes.SupervisionStrategy`](akka.stream.ActorAttributes$$SupervisionStrategy)]
@java[`ActorAttributes.SupervisionStrategy`] attribute.
Defers creation until a first element arrives.
## Reactive Streams semantics

View file

@ -0,0 +1,23 @@
# Sink.completionStageSink
Streams the elements to the given future sink once it successfully completes.
@ref[Sink operators](../index.md#sink-operators)
## Description
Streams the elements through the given future flow once it successfully completes.
If the future fails the stream is failed.
## Reactive Streams semantics
@@@div { .callout }
**cancels** if the future fails or if the created sink cancels
**backpressures** when initialized and when created sink backpressures
@@@

View file

@ -0,0 +1,30 @@
# Sink.futureSink
Streams the elements to the given future sink once it successfully completes.
@ref[Sink operators](../index.md#sink-operators)
@@@div { .group-scala }
## Signature
@@signature [Sink.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Sink.scala) { #futureSink }
@@@
## Description
Streams the elements through the given future flow once it successfully completes.
If the future fails the stream is failed.
## Reactive Streams semantics
@@@div { .callout }
**cancels** if the future fails or if the created sink cancels
**backpressures** when initialized and when created sink backpressures
@@@

View file

@ -0,0 +1,31 @@
# Sink.lazyCompletionStageSink
Defers creation and materialization of a `Sink` until there is a first element.
@ref[Sink operators](../index.md#sink-operators)
## Description
When the first element comes from upstream the `CompletionStage<Sink>` is created. When that completes successfully with a sink
that is materialized and inserted in the stream.
The internal `Sink` will not be created if the stream completes of fails before any element got through.
The materialized value of the `Sink` will be the materialized value of the created internal flow if it is materialized
and failed with a `akka.stream.NeverMaterializedException` if the stream fails or completes without the flow being materialized.
Can be combined with @ref:[prefixAndTail](../Source-or-Flow/prefixAndTail.md) to base the sink on the first element.
See also @ref:[lazySink](lazySink.md).
## Reactive Streams semantics
@@@div { .callout }
**cancels** if the future fails or if the created sink cancels
**backpressures** when initialized and when created sink backpressures
@@@

View file

@ -0,0 +1,38 @@
# Sink.lazyFutureSink
Defers creation and materialization of a `Sink` until there is a first element.
@ref[Sink operators](../index.md#sink-operators)
@@@div { .group-scala }
## Signature
@@signature [Sink.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Sink.scala) { #lazySink }
@@@
## Description
When the first element comes from upstream the `Future[Sink]` is created. When that completes successfully with a sink
that is materialized and inserted in the stream.
The internal `Sink` will not be created if the stream completes of fails before any element got through.
The materialized value of the `Sink` will be the materialized value of the created internal flow if it is materialized
and failed with a `akka.stream.NeverMaterializedException` if the stream fails or completes without the flow being materialized.
Can be combined with @ref:[prefixAndTail](../Source-or-Flow/prefixAndTail.md) to base the sink on the first element.
See also @ref:[lazySink](lazySink.md).
## Reactive Streams semantics
@@@div { .callout }
**cancels** if the future fails or if the created sink cancels
**backpressures** when initialized and when created sink backpressures
@@@

View file

@ -1,6 +1,6 @@
# Sink.lazyInitAsync
Creates a real `Sink` upon receiving the first element.
`lazyInitAsync` has been deprecated in 2.6.0, use `Sink.lazyFutureSink`
@ref[Sink operators](../index.md#sink-operators)
@ -14,6 +14,8 @@ Creates a real `Sink` upon receiving the first element.
## Description
`lazyInitAsync` has been deprecated in 2.6.0, use @ref:[lazyFutureSink](lazyFutureSink.md) instead.
Creates a real `Sink` upon receiving the first element. Internal `Sink` will not be created if there are no elements,
because of completion or error.

View file

@ -0,0 +1,37 @@
# Sink.lazySink
Defers creation and materialization of a `Sink` until there is a first element.
@ref[Sink operators](../index.md#sink-operators)
@@@div { .group-scala }
## Signature
@@signature [Sink.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Sink.scala) { #lazySink }
@@@
## Description
When the first element comes from upstream the actual `Sink` is created and materialized.
The internal `Sink` will not be created if the stream completes of fails before any element got through.
The materialized value of the `Sink` will be the materialized value of the created internal flow if it is materialized
and failed with a `akka.stream.NeverMaterializedException` if the stream fails or completes without the flow being materialized.
Can be combined with @ref[prefixAndTail](../Source-or-Flow/prefixAndTail.md) to base the sink on the first element.
See also @ref:[lazyFutureSink](lazyFutureSink.md) and @ref:[lazyCompletionStageSink](lazyCompletionStageSink.md).
## Reactive Streams semantics
@@@div { .callout }
**cancels** if the future fails or if the created sink cancels
**backpressures** when initialized and when created sink backpressures
@@@

View file

@ -0,0 +1,32 @@
# completionStage
Send the single value of the `CompletionStage` when it completes and there is demand.
@ref[Source operators](../index.md#source-operators)
@@@div { .group-scala }
## Signature
@@signature [Source.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Source.scala) { #completionStage }
@@@
## Description
Send the single value of the `CompletionStage` when it completes and there is demand.
If the `CompletionStage` completes with `null` stage is completed without emitting a value.
If the `CompletionStage` fails the stream is failed with that exception.
For the corresponding operator for the Scala standard library `Future` see @ref:[future](future.md).
## Reactive Streams semantics
@@@div { .callout }
**emits** the future completes
**completes** after the future has completed
@@@

View file

@ -0,0 +1,23 @@
# completionStageSource
Streams the elements of an asynchronous source once its given *completion* operator completes.
@ref[Source operators](../index.md#source-operators)
## Signature
## Description
Streams the elements of an asynchronous source once its given *completion* operator completes.
If the *completion* fails the stream is failed with that exception.
## Reactive Streams semantics
@@@div { .callout }
**emits** the next value from the asynchronous source, once its *completion operator* has completed
**completes** after the asynchronous source completes
@@@

View file

@ -1,6 +1,6 @@
# fromCompletionStage
Send the single value of the `CompletionStage` when it completes and there is demand.
`fromCompletionStage` has been deprecated in 2.6.0, use `Source.completionStage`
@ref[Source operators](../index.md#source-operators)
@ -14,6 +14,8 @@ Send the single value of the `CompletionStage` when it completes and there is de
## Description
`fromCompletionStage` has been deprecated in 2.6.0, use @ref:[completionStage](completionStage.md) instead.
Send the single value of the `CompletionStage` when it completes and there is demand.
If the `CompletionStage` completes with `null` stage is completed without emitting a value.
If the `CompletionStage` fails the stream is failed with that exception.

View file

@ -1,6 +1,6 @@
# fromFuture
Send the single value of the `Future` when it completes and there is demand.
`fromFuture` has been deprecated in 2.6.0, use `Source.future` instead.
@ref[Source operators](../index.md#source-operators)
@ -14,6 +14,8 @@ Send the single value of the `Future` when it completes and there is demand.
## Description
`fromFuture` has been deprecated in 2.6.0, use @ref:[future](future.md) instead.
Send the single value of the `Future` when it completes and there is demand.
If the future fails the stream is failed with that exception.
@ -28,6 +30,4 @@ If the future fails the stream is failed with that exception.
@@@
## Example
Scala
: @@snip [SourceFromFuture.scala](/akka-docs/src/test/scala/docs/stream/operators/SourceOperators.scala) { #sourceFromFuture }

View file

@ -1,6 +1,6 @@
# fromFutureSource
Streams the elements of the given future source once it successfully completes.
`fromFutureSource` has been deprecated in 2.6.0, use `Source.futureSource` instead.
@ref[Source operators](../index.md#source-operators)
@ -14,6 +14,8 @@ Streams the elements of the given future source once it successfully completes.
## Description
`fromFutureSource` has been deprecated in 2.6.0, use @ref:[futureSource](futureSource.md) instead.
Streams the elements of the given future source once it successfully completes.
If the future fails the stream is failed.

View file

@ -1,6 +1,6 @@
# fromSourceCompletionStage
Streams the elements of an asynchronous source once its given *completion* operator completes.
`fromSourceCompletionStage` has been deprecated in 2.6.0, use `Source.completionStageSource` instead.
@ref[Source operators](../index.md#source-operators)
@ -8,6 +8,8 @@ Streams the elements of an asynchronous source once its given *completion* opera
## Description
`fromSourceCompletionStage` has been deprecated in 2.6.0, use @ref:[completionStageSource](completionStageSource.md) instead.
Streams the elements of an asynchronous source once its given *completion* operator completes.
If the *completion* fails the stream is failed with that exception.

View file

@ -0,0 +1,35 @@
# fromFuture
Send the single value of the `Future` when it completes and there is demand.
@ref[Source operators](../index.md#source-operators)
@@@div { .group-scala }
## Signature
@@signature [Source.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Source.scala) { #future }
@@@
## Description
Send the single value of the `Future` when it completes and there is demand.
If the future fails the stream is failed with that exception.
For the corresponding operator for the Java standard library `CompletionStage` see @ref:[completionStage](completionStage.md).
## Reactive Streams semantics
@@@div { .callout }
**emits** the future completes
**completes** after the future has completed
@@@
## Example
Scala
: @@snip [SourceFromFuture.scala](/akka-docs/src/test/scala/docs/stream/operators/SourceOperators.scala) { #sourceFromFuture }

View file

@ -0,0 +1,29 @@
# futureSource
Streams the elements of the given future source once it successfully completes.
@ref[Source operators](../index.md#source-operators)
@@@div { .group-scala }
## Signature
@@signature [Source.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Source.scala) { #futureSource }
@@@
## Description
Streams the elements of the given future source once it successfully completes.
If the future fails the stream is failed.
## Reactive Streams semantics
@@@div { .callout }
**emits** the next value from the *future* source, once it has completed
**completes** after the *future* source completes
@@@

View file

@ -1,6 +1,6 @@
# lazily
Defers creation and materialization of a `Source` until there is demand.
`lazily` has been deprecated in 2.6.0, use `Source.lazySource` instead.
@ref[Source operators](../index.md#source-operators)
@ -14,6 +14,8 @@ Defers creation and materialization of a `Source` until there is demand.
## Description
`lazily` has been deprecated in 2.6.0, use @ref:[lazySource](lazySource.md) instead.
Defers creation and materialization of a `Source` until there is demand.
## Reactive Streams semantics

View file

@ -1,6 +1,6 @@
# lazilyAsync
Defers creation and materialization of a `CompletionStage` until there is demand.
`lazily` has been deprecated in 2.6.0, use `Source.lazyFutureSource` instead.
@ref[Source operators](../index.md#source-operators)
@ -8,6 +8,8 @@ Defers creation and materialization of a `CompletionStage` until there is demand
## Description
`lazily` has been deprecated in 2.6.0, use @ref:[lazyFutureSource](lazyFutureSource.md) instead.
Defers creation and materialization of a `CompletionStage` until there is demand.
## Reactive Streams semantics

View file

@ -0,0 +1,25 @@
# lazyCompletionStage
Defers creation of a future of a single element source until there is demand.
@ref[Source operators](../index.md#source-operators)
## Description
Invokes the user supplied factory when the first downstream demand arrives. When the returned future completes
successfully the value is emitted downstream as a single stream element. If the future or the factory fails the
stream is failed.
Note that asynchronous boundaries (and other operators) in the stream may do pre-fetching which counter acts
the laziness and will trigger the factory immediately.
## Reactive Streams semantics
@@@div { .callout }
**emits** when there is downstream demand and the element factory returned future has completed
**completes** after emitting the single element
@@@

View file

@ -0,0 +1,27 @@
# lazyCompletionStageSource
Defers creation of a future source until there is demand.
@ref[Source operators](../index.md#source-operators)
## Description
Invokes the user supplied factory when the first downstream demand arrives. When the returned `CompletionStage` completes
successfully the source switches over to the new source and emits downstream just like if it had been created up front. If the future or the factory fails the
stream is failed.
Note that asynchronous boundaries (and other operators) in the stream may do pre-fetching which counter acts
the laziness and will trigger the factory immediately.
See also @ref:[lazySource](lazySource.md).
## Reactive Streams semantics
@@@div { .callout }
**emits** depends on the wrapped `Source`
**completes** depends on the wrapped `Source`
@@@

View file

@ -0,0 +1,33 @@
# lazyFuture
Defers creation of a future of a single element source until there is demand.
@ref[Source operators](../index.md#source-operators)
@@@div { .group-scala }
## Signature
@@signature [Source.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Source.scala) { #lazyFuture }
@@@
## Description
Invokes the user supplied factory when the first downstream demand arrives. When the returned future completes
successfully the value is emitted downstream as a single stream element. If the future or the factory fails the
stream is failed.
Note that asynchronous boundaries (and other operators) in the stream may do pre-fetching which counter acts
the laziness and will trigger the factory immediately.
## Reactive Streams semantics
@@@div { .callout }
**emits** when there is downstream demand and the element factory returned future has completed
**completes** after emitting the single element
@@@

View file

@ -0,0 +1,34 @@
# lazyFutureSource
Defers creation and materialization of a `Source` until there is demand.
@ref[Source operators](../index.md#source-operators)
@@@div { .group-scala }
## Signature
@@signature [Source.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Source.scala) { #lazyFutureSource }
@@@
## Description
Invokes the user supplied factory when the first downstream demand arrives. When the returned future completes
successfully the source switches over to the new source and emits downstream just like if it had been created up front.
Note that asynchronous boundaries (and other operators) in the stream may do pre-fetching which counter acts
the laziness and will trigger the factory immediately.
See also @ref:[lazySource](lazySource.md).
## Reactive Streams semantics
@@@div { .callout }
**emits** depends on the wrapped `Source`
**completes** depends on the wrapped `Source`
@@@

View file

@ -0,0 +1,32 @@
# lazySingle
Defers creation of a single element source until there is demand.
@ref[Source operators](../index.md#source-operators)
@@@div { .group-scala }
## Signature
@@signature [Source.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Source.scala) { #lazySingle }
@@@
## Description
Invokes the user supplied factory when the first downstream demand arrives, then emits the returned single value
downstream and completes the stream.
Note that asynchronous boundaries (and other operators) in the stream may do pre-fetching which counter acts
the laziness and will trigger the factory immediately.
## Reactive Streams semantics
@@@div { .callout }
**emits** when there is downstream demand and the element factory has completed
**completes** after emitting the single element
@@@

View file

@ -0,0 +1,35 @@
# lazySource
Defers creation and materialization of a `Source` until there is demand.
@ref[Source operators](../index.md#source-operators)
@@@div { .group-scala }
## Signature
@@signature [Source.scala](/akka-stream/src/main/scala/akka/stream/scaladsl/Source.scala) { #lazySource }
@@@
## Description
Defers creation and materialization of a `Source` until there is demand, then emits the elements from the source
downstream just like if it had been created up front.
See also @ref:[lazyFutureSource](lazyFutureSource.md).
Note that asynchronous boundaries (and other operators) in the stream may do pre-fetching which counter acts
the laziness and will trigger the factory immediately.
## Reactive Streams semantics
@@@div { .callout }
**emits** depends on the wrapped `Source`
**completes** depends on the wrapped `Source`
@@@

View file

@ -12,18 +12,28 @@ These built-in sources are available from @scala[`akka.stream.scaladsl.Source`]
|Source|<a name="assourcewithcontext"></a>@ref[asSourceWithContext](Source/asSourceWithContext.md)|Turns a Source into a SourceWithContext which can propagate a context per element along a stream.|
|Source|<a name="assubscriber"></a>@ref[asSubscriber](Source/asSubscriber.md)|Integration with Reactive Streams, materializes into a `org.reactivestreams.Subscriber`.|
|Source|<a name="combine"></a>@ref[combine](Source/combine.md)|Combine several sources, using a given strategy such as merge or concat, into one source.|
|Source|<a name="completionstage"></a>@ref[completionStage](Source/completionStage.md)|Send the single value of the `CompletionStage` when it completes and there is demand.|
|Source|<a name="completionstagesource"></a>@ref[completionStageSource](Source/completionStageSource.md)|Streams the elements of an asynchronous source once its given *completion* operator completes.|
|Source|<a name="cycle"></a>@ref[cycle](Source/cycle.md)|Stream iterator in cycled manner.|
|Source|<a name="empty"></a>@ref[empty](Source/empty.md)|Complete right away without ever emitting any elements.|
|Source|<a name="failed"></a>@ref[failed](Source/failed.md)|Fail directly with a user specified exception.|
|Source|<a name="from"></a>@ref[@scala[apply]@java[from]](Source/from.md)|Stream the values of an @scala[`immutable.Seq`]@java[`Iterable`].|
|Source|<a name="fromcompletionstage"></a>@ref[fromCompletionStage](Source/fromCompletionStage.md)|Send the single value of the `CompletionStage` when it completes and there is demand.|
|Source|<a name="fromfuture"></a>@ref[fromFuture](Source/fromFuture.md)|Send the single value of the `Future` when it completes and there is demand.|
|Source|<a name="fromfuturesource"></a>@ref[fromFutureSource](Source/fromFutureSource.md)|Streams the elements of the given future source once it successfully completes.|
|Source|<a name="fromcompletionstage"></a>@ref[fromCompletionStage](Source/fromCompletionStage.md)|`fromCompletionStage` has been deprecated in 2.6.0, use `Source.completionStage`|
|Source|<a name="fromfuture"></a>@ref[fromFuture](Source/fromFuture.md)|`fromFuture` has been deprecated in 2.6.0, use `Source.future` instead.|
|Source|<a name="fromfuturesource"></a>@ref[fromFutureSource](Source/fromFutureSource.md)|`fromFutureSource` has been deprecated in 2.6.0, use `Source.futureSource` instead.|
|Source|<a name="fromiterator"></a>@ref[fromIterator](Source/fromIterator.md)|Stream the values from an `Iterator`, requesting the next value when there is demand.|
|Source|<a name="frompublisher"></a>@ref[fromPublisher](Source/fromPublisher.md)|Integration with Reactive Streams, subscribes to a `org.reactivestreams.Publisher`.|
|Source|<a name="fromsourcecompletionstage"></a>@ref[fromSourceCompletionStage](Source/fromSourceCompletionStage.md)|Streams the elements of an asynchronous source once its given *completion* operator completes.|
|Source|<a name="lazily"></a>@ref[lazily](Source/lazily.md)|Defers creation and materialization of a `Source` until there is demand.|
|Source|<a name="lazilyasync"></a>@ref[lazilyAsync](Source/lazilyAsync.md)|Defers creation and materialization of a `CompletionStage` until there is demand.|
|Source|<a name="fromsourcecompletionstage"></a>@ref[fromSourceCompletionStage](Source/fromSourceCompletionStage.md)|`fromSourceCompletionStage` has been deprecated in 2.6.0, use `Source.completionStageSource` instead.|
|Source|<a name="future"></a>@ref[future](Source/future.md)|Send the single value of the `Future` when it completes and there is demand.|
|Source|<a name="futuresource"></a>@ref[futureSource](Source/futureSource.md)|Streams the elements of the given future source once it successfully completes.|
|Source|<a name="lazily"></a>@ref[lazily](Source/lazily.md)|`lazily` has been deprecated in 2.6.0, use `Source.lazySource` instead.|
|Source|<a name="lazilyasync"></a>@ref[lazilyAsync](Source/lazilyAsync.md)|`lazily` has been deprecated in 2.6.0, use `Source.lazyFutureSource` instead.|
|Source|<a name="lazycompletionstage"></a>@ref[lazyCompletionStage](Source/lazyCompletionStage.md)|Defers creation of a future of a single element source until there is demand.|
|Source|<a name="lazycompletionstagesource"></a>@ref[lazyCompletionStageSource](Source/lazyCompletionStageSource.md)|Defers creation of a future source until there is demand.|
|Source|<a name="lazyfuture"></a>@ref[lazyFuture](Source/lazyFuture.md)|Defers creation of a future of a single element source until there is demand.|
|Source|<a name="lazyfuturesource"></a>@ref[lazyFutureSource](Source/lazyFutureSource.md)|Defers creation and materialization of a `Source` until there is demand.|
|Source|<a name="lazysingle"></a>@ref[lazySingle](Source/lazySingle.md)|Defers creation of a single element source until there is demand.|
|Source|<a name="lazysource"></a>@ref[lazySource](Source/lazySource.md)|Defers creation and materialization of a `Source` until there is demand.|
|Source|<a name="maybe"></a>@ref[maybe](Source/maybe.md)|Create a source that emits once the materialized @scala[`Promise`] @java[`CompletableFuture`] is completed with a value.|
|Source|<a name="queue"></a>@ref[queue](Source/queue.md)|Materialize a `SourceQueue` onto which elements can be pushed for emitting from the source. |
|Source|<a name="range"></a>@ref[range](Source/range.md)|Emit each integer in a range, with an option to take bigger steps than 1.|
@ -49,18 +59,23 @@ These built-in sinks are available from @scala[`akka.stream.scaladsl.Sink`] @jav
|Sink|<a name="aspublisher"></a>@ref[asPublisher](Sink/asPublisher.md)|Integration with Reactive Streams, materializes into a `org.reactivestreams.Publisher`.|
|Sink|<a name="cancelled"></a>@ref[cancelled](Sink/cancelled.md)|Immediately cancel the stream|
|Sink|<a name="combine"></a>@ref[combine](Sink/combine.md)|Combine several sinks into one using a user specified strategy|
|Sink|<a name="completionstagesink"></a>@ref[completionStageSink](Sink/completionStageSink.md)|Streams the elements to the given future sink once it successfully completes. |
|Sink|<a name="fold"></a>@ref[fold](Sink/fold.md)|Fold over emitted element with a function, where each invocation will get the new element and the result from the previous fold invocation.|
|Sink|<a name="foreach"></a>@ref[foreach](Sink/foreach.md)|Invoke a given procedure for each element received.|
|Sink|<a name="foreachasync"></a>@ref[foreachAsync](Sink/foreachAsync.md)|Invoke a given procedure asynchronously for each element received.|
|Sink|<a name="foreachparallel"></a>@ref[foreachParallel](Sink/foreachParallel.md)|Like `foreach` but allows up to `parallellism` procedure calls to happen in parallel.|
|Sink|<a name="frommaterializer"></a>@ref[fromMaterializer](Sink/fromMaterializer.md)|Defer the creation of a `Sink` until materialization and access `Materializer` and `Attributes`|
|Sink|<a name="fromsubscriber"></a>@ref[fromSubscriber](Sink/fromSubscriber.md)|Integration with Reactive Streams, wraps a `org.reactivestreams.Subscriber` as a sink.|
|Sink|<a name="futuresink"></a>@ref[futureSink](Sink/futureSink.md)|Streams the elements to the given future sink once it successfully completes. |
|Sink|<a name="head"></a>@ref[head](Sink/head.md)|Materializes into a @scala[`Future`] @java[`CompletionStage`] which completes with the first value arriving, after this the stream is canceled.|
|Sink|<a name="headoption"></a>@ref[headOption](Sink/headOption.md)|Materializes into a @scala[`Future[Option[T]]`] @java[`CompletionStage<Optional<T>>`] which completes with the first value arriving wrapped in @scala[`Some`] @java[`Optional`], or @scala[a `None`] @java[an empty Optional] if the stream completes without any elements emitted.|
|Sink|<a name="ignore"></a>@ref[ignore](Sink/ignore.md)|Consume all elements but discards them.|
|Sink|<a name="last"></a>@ref[last](Sink/last.md)|Materializes into a @scala[`Future`] @java[`CompletionStage`] which will complete with the last value emitted when the stream completes.|
|Sink|<a name="lastoption"></a>@ref[lastOption](Sink/lastOption.md)|Materialize a @scala[`Future[Option[T]]`] @java[`CompletionStage<Optional<T>>`] which completes with the last value emitted wrapped in an @scala[`Some`] @java[`Optional`] when the stream completes.|
|Sink|<a name="lazyinitasync"></a>@ref[lazyInitAsync](Sink/lazyInitAsync.md)|Creates a real `Sink` upon receiving the first element. |
|Sink|<a name="lazycompletionstagesink"></a>@ref[lazyCompletionStageSink](Sink/lazyCompletionStageSink.md)|Defers creation and materialization of a `Sink` until there is a first element.|
|Sink|<a name="lazyfuturesink"></a>@ref[lazyFutureSink](Sink/lazyFutureSink.md)|Defers creation and materialization of a `Sink` until there is a first element.|
|Sink|<a name="lazyinitasync"></a>@ref[lazyInitAsync](Sink/lazyInitAsync.md)|`lazyInitAsync` has been deprecated in 2.6.0, use `Sink.lazyFutureSink` |
|Sink|<a name="lazysink"></a>@ref[lazySink](Sink/lazySink.md)|Defers creation and materialization of a `Sink` until there is a first element.|
|Sink|<a name="oncomplete"></a>@ref[onComplete](Sink/onComplete.md)|Invoke a callback when the stream has completed or failed.|
|Sink|<a name="prematerialize"></a>@ref[preMaterialize](Sink/preMaterialize.md)|Materializes this Sink, immediately returning (1) its materialized value, and (2) a new Sink that can be consume elements 'into' the pre-materialized one.|
|Sink|<a name="queue"></a>@ref[queue](Sink/queue.md)|Materialize a `SinkQueue` that can be pulled to trigger demand through the sink.|
@ -129,6 +144,7 @@ depending on being backpressured by downstream or not.
|Flow|<a name="asflowwithcontext"></a>@ref[asFlowWithContext](Flow/asFlowWithContext.md)|Turns a Flow into a FlowWithContext which can propagate a context per element along a stream.|
|Source/Flow|<a name="collect"></a>@ref[collect](Source-or-Flow/collect.md)|Apply a partial function to each incoming element, if the partial function is defined for a value the returned value is passed downstream.|
|Source/Flow|<a name="collecttype"></a>@ref[collectType](Source-or-Flow/collectType.md)|Transform this stream by testing the type of each of the elements on which the element is an instance of the provided type as they pass through this processing step.|
|Flow|<a name="completionstageflow"></a>@ref[completionStageFlow](Flow/completionStageFlow.md)|Streams the elements through the given future flow once it successfully completes.|
|Source/Flow|<a name="detach"></a>@ref[detach](Source-or-Flow/detach.md)|Detach upstream demand from downstream demand without detaching the stream rates.|
|Source/Flow|<a name="drop"></a>@ref[drop](Source-or-Flow/drop.md)|Drop `n` elements and then pass any subsequent element downstream.|
|Source/Flow|<a name="dropwhile"></a>@ref[dropWhile](Source-or-Flow/dropWhile.md)|Drop elements as long as a predicate function return true for the element|
@ -137,9 +153,13 @@ depending on being backpressured by downstream or not.
|Source/Flow|<a name="fold"></a>@ref[fold](Source-or-Flow/fold.md)|Start with current value `zero` and then apply the current and next value to the given function. When upstream completes, the current value is emitted downstream.|
|Source/Flow|<a name="foldasync"></a>@ref[foldAsync](Source-or-Flow/foldAsync.md)|Just like `fold` but receives a function that results in a @scala[`Future`] @java[`CompletionStage`] to the next value.|
|Source/Flow|<a name="frommaterializer"></a>@ref[fromMaterializer](Source-or-Flow/fromMaterializer.md)|Defer the creation of a `Source/Flow` until materialization and access `Materializer` and `Attributes`|
|Flow|<a name="futureflow"></a>@ref[futureFlow](Flow/futureFlow.md)|Streams the elements through the given future flow once it successfully completes.|
|Source/Flow|<a name="grouped"></a>@ref[grouped](Source-or-Flow/grouped.md)|Accumulate incoming events until the specified number of elements have been accumulated and then pass the collection of elements downstream.|
|Source/Flow|<a name="intersperse"></a>@ref[intersperse](Source-or-Flow/intersperse.md)|Intersperse stream with provided element similar to `List.mkString`.|
|Flow|<a name="lazyinitasync"></a>@ref[lazyInitAsync](Flow/lazyInitAsync.md)|Creates a real `Flow` upon receiving the first element by calling relevant `flowFactory` given as an argument.|
|Flow|<a name="lazycompletionstageflow"></a>@ref[lazyCompletionStageFlow](Flow/lazyCompletionStageFlow.md)|Defers creation and materialization of a `Flow` until there is a first element.|
|Flow|<a name="lazyflow"></a>@ref[lazyFlow](Flow/lazyFlow.md)|Defers creation and materialization of a `Flow` until there is a first element.|
|Flow|<a name="lazyfutureflow"></a>@ref[lazyFutureFlow](Flow/lazyFutureFlow.md)|Defers creation and materialization of a `Flow` until there is a first element.|
|Flow|<a name="lazyinitasync"></a>@ref[lazyInitAsync](Flow/lazyInitAsync.md)|`lazyInitAsync` has been deprecated in 2.6.0 use `Flow.lazyFutureFlow` in combination with `prefixAndTail` instead.|
|Source/Flow|<a name="limit"></a>@ref[limit](Source-or-Flow/limit.md)|Limit number of element from upstream to given `max` number.|
|Source/Flow|<a name="limitweighted"></a>@ref[limitWeighted](Source-or-Flow/limitWeighted.md)|Ensure stream boundedness by evaluating the cost of incoming elements using a cost function.|
|Source/Flow|<a name="log"></a>@ref[log](Source-or-Flow/log.md)|Log elements flowing through the stream as well as completion and erroring.|
@ -337,6 +357,13 @@ For more background see the @ref[Error Handling in Streams](../stream-error.md)
* [failed](Source/failed.md)
* [lazily](Source/lazily.md)
* [lazilyAsync](Source/lazilyAsync.md)
* [future](Source/future.md)
* [completionStage](Source/completionStage.md)
* [futureSource](Source/futureSource.md)
* [lazySingle](Source/lazySingle.md)
* [lazyFuture](Source/lazyFuture.md)
* [lazySource](Source/lazySource.md)
* [lazyFutureSource](Source/lazyFutureSource.md)
* [asSubscriber](Source/asSubscriber.md)
* [actorRef](Source/actorRef.md)
* [actorRefWithBackpressure](Source/actorRefWithBackpressure.md)
@ -347,6 +374,9 @@ For more background see the @ref[Error Handling in Streams](../stream-error.md)
* [unfoldResourceAsync](Source/unfoldResourceAsync.md)
* [@scala[apply]@java[from]](Source/from.md)
* [range](Source/range.md)
* [completionStageSource](Source/completionStageSource.md)
* [lazyCompletionStage](Source/lazyCompletionStage.md)
* [lazyCompletionStageSource](Source/lazyCompletionStageSource.md)
* [concat](Source-or-Flow/concat.md)
* [prepend](Source-or-Flow/prepend.md)
* [orElse](Source-or-Flow/orElse.md)
@ -427,6 +457,11 @@ For more background see the @ref[Error Handling in Streams](../stream-error.md)
* [fromSinkAndSource](Flow/fromSinkAndSource.md)
* [fromSinkAndSourceCoupled](Flow/fromSinkAndSourceCoupled.md)
* [lazyInitAsync](Flow/lazyInitAsync.md)
* [futureFlow](Flow/futureFlow.md)
* [lazyFlow](Flow/lazyFlow.md)
* [lazyFutureFlow](Flow/lazyFutureFlow.md)
* [completionStageFlow](Flow/completionStageFlow.md)
* [lazyCompletionStageFlow](Flow/lazyCompletionStageFlow.md)
* [preMaterialize](Sink/preMaterialize.md)
* [fromMaterializer](Sink/fromMaterializer.md)
* [setup](Sink/setup.md)
@ -451,6 +486,11 @@ For more background see the @ref[Error Handling in Streams](../stream-error.md)
* [actorRefWithBackpressure](Sink/actorRefWithBackpressure.md)
* [queue](Sink/queue.md)
* [lazyInitAsync](Sink/lazyInitAsync.md)
* [futureSink](Sink/futureSink.md)
* [lazySink](Sink/lazySink.md)
* [lazyFutureSink](Sink/lazyFutureSink.md)
* [completionStageSink](Sink/completionStageSink.md)
* [lazyCompletionStageSink](Sink/lazyCompletionStageSink.md)
* [fromInputStream](StreamConverters/fromInputStream.md)
* [asOutputStream](StreamConverters/asOutputStream.md)
* [fromOutputStream](StreamConverters/fromOutputStream.md)

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
*/
package jdocs.stream.operators.flow;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Source;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
public class FutureFlow {
private ActorSystem system = null;
// #base-on-first-element
CompletionStage<Flow<Integer, String, NotUsed>> processingFlow(int id) {
return CompletableFuture.completedFuture(
Flow.of(Integer.class).map(n -> "id: " + id + " value: " + n));
}
// #base-on-first-element
public void compileOnlyBaseOnFirst() {
// #base-on-first-element
Source<String, NotUsed> source =
Source.range(1, 10)
.prefixAndTail(1)
.flatMapConcat(
(pair) -> {
List<Integer> head = pair.first();
Source<Integer, NotUsed> tail = pair.second();
int id = head.get(0);
return tail.via(Flow.completionStageFlow(processingFlow(id)));
});
// #base-on-first-element
}
}

View file

@ -20,7 +20,7 @@ object SourceOperators {
import scala.concurrent.Future
val source: Source[Int, NotUsed] = Source.fromFuture(Future.successful(10))
val source: Source[Int, NotUsed] = Source.future(Future.successful(10))
val sink: Sink[Int, Future[Done]] = Sink.foreach((i: Int) => println(i))
val done: Future[Done] = source.runWith(sink) //10

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
*/
package docs.stream.operators.flow
import akka.NotUsed
import akka.actor.ActorSystem
import akka.stream.scaladsl.Flow
import akka.stream.scaladsl.Source
import scala.concurrent.Future
class FutureFlow {
implicit val system: ActorSystem = ???
import system.dispatcher
def compileOnlyBaseOnFirst(): Unit = {
// #base-on-first-element
def processingFlow(id: Int): Future[Flow[Int, String, NotUsed]] =
Future {
Flow[Int].map(n => s"id: $id, value: $n")
}
val source: Source[String, NotUsed] =
Source(1 to 10).prefixAndTail(1).flatMapConcat {
case (List(id), tail) =>
// base the Future flow creation on the first element
tail.via(Flow.futureFlow(processingFlow(id)))
}
// #base-on-first-element
}
}