ASe ASe - 10 months ago 82
Scala Question

akka stream toMat

I am trying to understand what does toMat in akka streaming. For example:

val sink1:Sink[Int, Future[Int]]=Sink.fold[Int,Int](0)(_ + _)

val flow=Flow[Int].fold[Int](0){(x,y)=> x+y}

val runnable = Source (1 to 10).viaMat(flow)(Keep.right).toMat(sink1)(Keep.both)

  1. what is use of viaMat vs via?

  2. what is toMat is doing between viaMat to toMat?

  3. what is use of keep.both, does it mean I can have value materialized from previous and the current one if yes then how I can get those values back.


Answer Source
  1. via is just a shortcut for viaMat(...)(Keep.left), and in fact this is how it's implemented: override def via[T, Mat2](flow: Graph[FlowShape[Out, T], Mat2]): Repr[T] = viaMat(flow)(Keep.left)

  2. toMat is the same as viaMat but for sinks, it lets you keep the materialized value from the left (source/flow) or right (sink) side or both

  3. Keep.both is just an alias for (a:A,b:B) => (a, b), that is a function that takes the two input parameters and return them as a tuple. It's used to have the materialized value of both left and right side when combining two flows (or source and flow or flow and sink etc)

I'll dissect your line of code:

// you're keeping the materialized value of flow
val source2 = Source (1 to 10).viaMat(flow)(Keep.right)
// you're keeping both materialized values, i.e. the one of flow from previous step
// and the one o sink.     
val runnableGraph = source2.toMat(sink)(Keep.both) // returns a tuple (flowMatVal, sinkMatVal)

When you join two parts of a flow (i.e source and flow/sink or flow and sink) each of them has a materialized value that you get when you run the flow. The default behaviour when combining with via/to is keeping the left side. If you use viaMat/toMat you can choose to keep the right materialized value or both of them as a tuple.