问题
In Akka streams what does Mat in Source[Out, Mat] or Sink[In, Mat] represent. When will it actually be used?
回答1:
The Mat
type parameter represents the type of the materialized value of this stream.
Remember that in Akka Source
, Flow
, Sink
(well, all graphs) are just blueprints - they do not do any processing by themselves, they only describe how the stream should be constructed. The process of turning these blueprints into a working stream with live data is called materialization.
The core method for materializing a stream is called run()
, and it is defined in the RunnableGraph
class. All other methods to run a stream (e.g. runWith
on a Sink
or Source
) eventually delegate to this method. You can see that this method returns Mat
. That is, materializing a stream yields a materialized value.
For example, there is a sink which combines all the values in a stream into a single value, it is constructed with Sink.fold. But how do you get this value? Since the stream is running asynchronously, a natural type for this value would be Future[T]
, where T
is the type of the fold accumulator. Turns out, Sink.fold
returns Sink[In, Future[T]]
, that is, this Future[T]
is its materialized value, therefore, when you materialize it, you get an instance of Future[T]
which you can then use in your own code for further processing: it will complete with a value if the stream completes correctly and it will complete with a failure if the stream has terminated with an exception.
Each part of the graph you construct by combining sinks, sources and flows (and other kinds of graphs) may potentially have an associated materialized value. For example, materialized value of Source.queue is a queue which you can use to push elements to the stream once it is materialized, and materialized value of Sink.actorSubscriber
is an ActorRef
which you can use to interact with the actor (which is created by the materializer when the stream is materialized). On the other hand, there is Flow.map
which is a flow with no meaningful materialized value (there is nothing you can externally control when you only apply a pure function to a stream), therefore its materialized value is NotUsed
, which is essentially Unit
.
Naturally, it is possible for different parts of stream contain their own materialized value. For example, nothing prevents you from combining Source.queue
and Sink.fold
. But RunnableGraph.run()
can only return one materialized value. To overcome this, there are usually two variants of combining methods on Sink
s, Flow
s, and other graphs, usually called like method
and methodMat
, e.g. to and toMat. The second variant allows you to choose how to combine materialized values of the streams you are joining. For example, you can put them into a tuple to get them both:
val (queue, future) = Source.queue[Int](10, OverflowStrategy.fail)
.map(x => x + 10)
.toMat(Sink.fold(0)(_ + _))(Keep.both)
.run()
Default combination methods (without the Mat
suffix) usually choose either the left or the right materialized value, depending on what would be the most natural thing to do for this particular kind of stream. The Keep object contains convenience methods which return either left, right or both arguments, specifically for the purpose of using them as the last argument for *Mat
methods, but nothing prevents you from writing your own combining function.
来源:https://stackoverflow.com/questions/39727729/akka-streams-what-does-mat-represents-in-sourceout-mat