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

@ -16,13 +16,14 @@ import akka.stream.{ Outlet, SourceShape, _ }
import akka.util.ConstantFun
import akka.{ Done, NotUsed }
import org.reactivestreams.{ Publisher, Subscriber }
import scala.annotation.tailrec
import scala.annotation.unchecked.uncheckedVariance
import scala.collection.immutable
import scala.concurrent.duration.FiniteDuration
import scala.concurrent.{ Future, Promise }
import akka.stream.stage.GraphStageWithMaterializedValue
import scala.compat.java8.FutureConverters._
/**
@ -341,6 +342,7 @@ object Source {
* may happen before or after materializing the `Flow`.
* The stream terminates with a failure if the `Future` is completed with a failure.
*/
@deprecated("Use 'Source.future' instead", "2.6.0")
def fromFuture[T](future: Future[T]): Source[T, NotUsed] =
fromGraph(new FutureSource(future))
@ -350,6 +352,7 @@ object Source {
* may happen before or after materializing the `Flow`.
* The stream terminates with a failure if the `Future` is completed with a failure.
*/
@deprecated("Use 'Source.completionStage' instead", "2.6.0")
def fromCompletionStage[T](future: CompletionStage[T]): Source[T, NotUsed] =
fromGraph(new FutureSource(future.toScala))
@ -358,6 +361,7 @@ object Source {
* If the [[Future]] fails the stream is failed with the exception from the future. If downstream cancels before the
* stream completes the materialized `Future` will be failed with a [[StreamDetachedException]]
*/
@deprecated("Use 'Source.futureSource' (potentially together with `Source.fromGraph`) instead", "2.6.0")
def fromFutureSource[T, M](future: Future[Graph[SourceShape[T], M]]): Source[T, Future[M]] =
fromGraph(new FutureFlattenSource(future))
@ -367,6 +371,7 @@ object Source {
* If downstream cancels before the stream completes the materialized `Future` will be failed
* with a [[StreamDetachedException]]
*/
@deprecated("Use scala-compat CompletionStage to future converter and 'Source.futureSource' instead", "2.6.0")
def fromSourceCompletionStage[T, M](
completion: CompletionStage[_ <: Graph[SourceShape[T], M]]): Source[T, CompletionStage[M]] =
fromFutureSource(completion.toScala).mapMaterializedValue(_.toJava)
@ -462,6 +467,7 @@ object Source {
* the materialized future is completed with its value, if downstream cancels or fails without any demand the
* create factory is never called and the materialized `Future` is failed.
*/
@deprecated("Use 'Source.lazySource' instead", "2.6.0")
def lazily[T, M](create: () => Source[T, M]): Source[T, Future[M]] =
Source.fromGraph(new LazySource[T, M](create))
@ -472,9 +478,98 @@ object Source {
*
* @see [[Source.lazily]]
*/
@deprecated("Use 'Source.lazyFuture' instead", "2.6.0")
def lazilyAsync[T](create: () => Future[T]): Source[T, Future[NotUsed]] =
lazily(() => fromFuture(create()))
/**
* Emits a single value when the given `Future` is successfully completed and then completes the stream.
* The stream fails if the `Future` is completed with a failure.
*/
def future[T](futureElement: Future[T]): Source[T, NotUsed] =
fromGraph(new FutureSource[T](futureElement))
/**
* Emits a single value when the given `CompletionStage` is successfully completed and then completes the stream.
* If the `CompletionStage` is completed with a failure the stream is failed.
*
* Here for Java interoperability, the normal use from Scala should be [[Source.future]]
*/
def completionStage[T](completionStage: CompletionStage[T]): Source[T, NotUsed] =
future(completionStage.toScala)
/**
* Turn a `Future[Source]` into a source that will emit the values of the source when the future completes successfully.
* If the `Future` is completed with a failure the stream is failed.
*/
def futureSource[T, M](futureSource: Future[Source[T, M]]): Source[T, Future[M]] =
fromGraph(new FutureFlattenSource(futureSource))
/**
* Defers invoking the `create` function to create a single element until there is downstream demand.
*
* If the `create` function fails when invoked 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.
*/
def lazySingle[T](create: () => T): Source[T, NotUsed] =
lazySource(() => single(create())).mapMaterializedValue(_ => NotUsed)
/**
* Defers invoking the `create` function to create a future element until there is downstream demand.
*
* The returned future element will be emitted downstream when it completes, or fail the stream if the future
* is failed or the `create` function itself fails.
*
* 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.
*/
def lazyFuture[T](create: () => Future[T]): Source[T, NotUsed] =
lazySource { () =>
val f = create()
future(f)
}.mapMaterializedValue(_ => NotUsed)
/**
* Defers invoking the `create` function to create a future source until there is downstream demand.
*
* The returned source will emit downstream and behave just like it was the outer source. Downstream completes
* when the created source completes and fails when the created source fails.
*
* 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.
*
* The materialized future value is completed with the materialized value of the created source when
* it has been materialized. If the function throws or the source materialization fails the future materialized value
* is failed with the thrown exception.
*
* If downstream cancels or fails before the function is invoked the materialized value
* is failed with a [[akka.stream.NeverMaterializedException]]
*/
def lazySource[T, M](create: () => Source[T, M]): Source[T, Future[M]] =
fromGraph(new LazySource(create))
/**
* Defers invoking the `create` function to create a future source until there is downstream demand.
*
* The returned future source will emit downstream and behave just like it was the outer source when the future completes
* successfully. Downstream completes when the created source completes and fails when the created source fails.
* If the future or the `create` function 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 triggers the factory immediately.
*
* The materialized future value is completed with the materialized value of the created source when
* it has been materialized. If the function throws or the source materialization fails the future materialized value
* is failed with the thrown exception.
*
* If downstream cancels or fails before the function is invoked the materialized value
* is failed with a [[akka.stream.NeverMaterializedException]]
*/
def lazyFutureSource[T, M](create: () => Future[Source[T, M]]): Source[T, Future[M]] =
lazySource(() => futureSource(create())).mapMaterializedValue(_.flatten)
/**
* Creates a `Source` that is materialized as a [[org.reactivestreams.Subscriber]]
*/