6

I have a stream like this and two sinks, but only one is used at a time:

Source.fromElements(1, 2, 3)
.via(flow)
.runWith(sink1)

or

Source.fromElements(1, 2, 3)
.via(flow)
.runWith(sink2)

It is configurable which sink we use, but what if I have use both sinks in parallel. How can I do that?

I thought about Sink.combine, but it requires also a merge strategy and I don't want to combine results of these sinks in any way. I don't really care about them, so I want to only send the same data via HTTP to some endpoint while in the same time send them to database. Sink combine is very similar to broadcast, but implementing a broadcast from the scratch decreases readability of my code where now I have only simple source, flow and a sink, no low-level graph stages.

Do you know a proper way how to do that (having backpressure and other things that I have using only one sink)?

Piotr Kozlowski
  • 899
  • 1
  • 13
  • 25

2 Answers2

12

You can use alsoTo (see API docs):

Flow[Int].alsoTo(Sink.foreach(println(_))).to(Sink.ignore)
Sebastian
  • 16,813
  • 4
  • 49
  • 56
  • 2
    How can I run these sinks in parallel, by adding a simple .async before the second sink? I would like to run them in parallel, but still have a backpressure, in other words I would like to have my stream running as fast as the time spent in the slowest sink and not as the sum of time spent in all the sinks (because they are run synchronously). – Piotr Kozlowski Jan 15 '18 at 10:39
  • 3
    It's worth mentioning that sink from alsoTo() will be executed at the end, after sink declared in to(). – Piotr Kozlowski Oct 30 '18 at 13:03
4

Broadcasting using GraphDSL in its simplest form shouldn't decrease readability – in fact, one might even argue that the ~> clauses in some way help visualize the stream structure:

val graph = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder =>
  import GraphDSL.Implicits._
  val bcast = builder.add(Broadcast[Int](2))

  Source.fromElements(1, 2, 3) ~> flow ~> bcast.in
  bcast.out(0) ~> sink1
  bcast.out(1) ~> sink2

  ClosedShape
})
graph.run()
Leo C
  • 22,006
  • 3
  • 26
  • 39
  • Are these sinks run in parallel? – Piotr Kozlowski Jan 15 '18 at 20:52
  • By default, Akka Streams execute graph processing stages sequentially, but if wanted you can execute them in parallel using method `async`. For more details, here's a [Akka Stream doc](https://doc.akka.io/docs/akka/current/stream/stream-parallelism.html?language=scala) on the topic. – Leo C Jan 15 '18 at 21:35