2014-12-11 14:57:48 +01:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2014 Typesafe Inc. <http://www.typesafe.com>
|
|
|
|
|
*/
|
|
|
|
|
package docs.stream
|
|
|
|
|
|
2015-06-29 23:47:31 -04:00
|
|
|
import akka.actor.ActorRef
|
2015-01-28 14:19:50 +01:00
|
|
|
import akka.stream._
|
2015-06-29 23:47:31 -04:00
|
|
|
import akka.stream.scaladsl._
|
2014-12-11 14:57:48 +01:00
|
|
|
import akka.stream.testkit.AkkaSpec
|
|
|
|
|
|
2015-06-29 23:47:31 -04:00
|
|
|
import scala.concurrent.{ Await, Future }
|
2014-12-11 14:57:48 +01:00
|
|
|
import scala.concurrent.duration._
|
|
|
|
|
|
2014-12-11 14:57:48 +01:00
|
|
|
class StreamPartialFlowGraphDocSpec extends AkkaSpec {
|
|
|
|
|
|
2014-12-11 14:57:48 +01:00
|
|
|
implicit val ec = system.dispatcher
|
|
|
|
|
|
2015-06-23 18:28:53 +02:00
|
|
|
implicit val mat = ActorMaterializer()
|
2014-12-11 14:57:48 +01:00
|
|
|
|
|
|
|
|
"build with open ports" in {
|
|
|
|
|
//#simple-partial-flow-graph
|
2015-10-21 22:45:39 +02:00
|
|
|
val pickMaxOfThree = FlowGraph.create() { implicit b =>
|
2015-01-28 14:19:50 +01:00
|
|
|
import FlowGraph.Implicits._
|
|
|
|
|
|
|
|
|
|
val zip1 = b.add(ZipWith[Int, Int, Int](math.max _))
|
|
|
|
|
val zip2 = b.add(ZipWith[Int, Int, Int](math.max _))
|
|
|
|
|
zip1.out ~> zip2.in0
|
|
|
|
|
|
|
|
|
|
UniformFanInShape(zip2.out, zip1.in0, zip1.in1, zip2.in1)
|
2014-12-11 14:57:48 +01:00
|
|
|
}
|
2014-12-11 14:57:48 +01:00
|
|
|
|
|
|
|
|
val resultSink = Sink.head[Int]
|
|
|
|
|
|
2015-10-21 22:45:39 +02:00
|
|
|
val g = RunnableGraph.fromGraph(FlowGraph.create(resultSink) { implicit b =>
|
2015-01-28 14:19:50 +01:00
|
|
|
sink =>
|
|
|
|
|
import FlowGraph.Implicits._
|
|
|
|
|
|
|
|
|
|
// importing the partial graph will return its shape (inlets & outlets)
|
|
|
|
|
val pm3 = b.add(pickMaxOfThree)
|
2014-12-11 14:57:48 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
Source.single(1) ~> pm3.in(0)
|
|
|
|
|
Source.single(2) ~> pm3.in(1)
|
|
|
|
|
Source.single(3) ~> pm3.in(2)
|
|
|
|
|
pm3.out ~> sink.inlet
|
2015-10-21 22:45:39 +02:00
|
|
|
ClosedShape
|
|
|
|
|
})
|
2014-12-11 14:57:48 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
val max: Future[Int] = g.run()
|
2014-12-11 14:57:48 +01:00
|
|
|
Await.result(max, 300.millis) should equal(3)
|
2014-12-11 14:57:48 +01:00
|
|
|
//#simple-partial-flow-graph
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-11 14:57:48 +01:00
|
|
|
"build source from partial flow graph" in {
|
|
|
|
|
//#source-from-partial-flow-graph
|
2015-10-21 22:45:39 +02:00
|
|
|
val pairs = Source.fromGraph(FlowGraph.create() { implicit b =>
|
2015-01-28 14:19:50 +01:00
|
|
|
import FlowGraph.Implicits._
|
2014-12-11 14:57:48 +01:00
|
|
|
|
|
|
|
|
// prepare graph elements
|
2015-01-28 14:19:50 +01:00
|
|
|
val zip = b.add(Zip[Int, Int]())
|
2014-12-22 16:18:26 +01:00
|
|
|
def ints = Source(() => Iterator.from(1))
|
2014-12-11 14:57:48 +01:00
|
|
|
|
|
|
|
|
// connect the graph
|
2015-02-26 16:37:16 +01:00
|
|
|
ints.filter(_ % 2 != 0) ~> zip.in0
|
|
|
|
|
ints.filter(_ % 2 == 0) ~> zip.in1
|
2014-12-11 14:57:48 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
// expose port
|
2015-10-21 22:45:39 +02:00
|
|
|
SourceShape(zip.out)
|
|
|
|
|
})
|
2014-12-11 14:57:48 +01:00
|
|
|
|
2015-03-05 12:21:17 +01:00
|
|
|
val firstPair: Future[(Int, Int)] = pairs.runWith(Sink.head)
|
2014-12-11 14:57:48 +01:00
|
|
|
//#source-from-partial-flow-graph
|
2015-01-16 17:55:03 +01:00
|
|
|
Await.result(firstPair, 300.millis) should equal(1 -> 2)
|
2014-12-11 14:57:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"build flow from partial flow graph" in {
|
|
|
|
|
//#flow-from-partial-flow-graph
|
2015-10-21 22:45:39 +02:00
|
|
|
val pairUpWithToString =
|
|
|
|
|
Flow.fromGraph(FlowGraph.create() { implicit b =>
|
|
|
|
|
import FlowGraph.Implicits._
|
2014-12-11 14:57:48 +01:00
|
|
|
|
2015-10-21 22:45:39 +02:00
|
|
|
// prepare graph elements
|
|
|
|
|
val broadcast = b.add(Broadcast[Int](2))
|
|
|
|
|
val zip = b.add(Zip[Int, String]())
|
2014-12-11 14:57:48 +01:00
|
|
|
|
2015-10-21 22:45:39 +02:00
|
|
|
// connect the graph
|
|
|
|
|
broadcast.out(0).map(identity) ~> zip.in0
|
|
|
|
|
broadcast.out(1).map(_.toString) ~> zip.in1
|
2014-12-11 14:57:48 +01:00
|
|
|
|
2015-10-21 22:45:39 +02:00
|
|
|
// expose ports
|
|
|
|
|
FlowShape(broadcast.in, zip.out)
|
|
|
|
|
})
|
2014-12-11 14:57:48 +01:00
|
|
|
|
|
|
|
|
//#flow-from-partial-flow-graph
|
|
|
|
|
|
|
|
|
|
// format: OFF
|
|
|
|
|
val (_, matSink: Future[(Int, String)]) =
|
|
|
|
|
//#flow-from-partial-flow-graph
|
2015-03-05 12:21:17 +01:00
|
|
|
pairUpWithToString.runWith(Source(List(1)), Sink.head)
|
2014-12-11 14:57:48 +01:00
|
|
|
//#flow-from-partial-flow-graph
|
|
|
|
|
// format: ON
|
|
|
|
|
|
2015-01-16 17:55:03 +01:00
|
|
|
Await.result(matSink, 300.millis) should equal(1 -> "1")
|
2014-12-11 14:57:48 +01:00
|
|
|
}
|
2015-06-29 23:47:31 -04:00
|
|
|
|
|
|
|
|
"combine sources with simplified API" in {
|
|
|
|
|
//#source-combine
|
|
|
|
|
val sourceOne = Source(List(1))
|
|
|
|
|
val sourceTwo = Source(List(2))
|
|
|
|
|
val merged = Source.combine(sourceOne, sourceTwo)(Merge(_))
|
|
|
|
|
|
|
|
|
|
val mergedResult: Future[Int] = merged.runWith(Sink.fold(0)(_ + _))
|
|
|
|
|
//#source-combine
|
|
|
|
|
Await.result(mergedResult, 300.millis) should equal(3)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"combine sinks with simplified API" in {
|
|
|
|
|
val actorRef: ActorRef = testActor
|
|
|
|
|
//#sink-combine
|
|
|
|
|
val sendRmotely = Sink.actorRef(actorRef, "Done")
|
|
|
|
|
val localProcessing = Sink.foreach[Int](_ => /* do something usefull */ ())
|
|
|
|
|
|
2015-10-08 12:12:35 +02:00
|
|
|
val sink = Sink.combine(sendRmotely, localProcessing)(Broadcast[Int](_))
|
2015-06-29 23:47:31 -04:00
|
|
|
|
|
|
|
|
Source(List(0, 1, 2)).runWith(sink)
|
|
|
|
|
//#sink-combine
|
|
|
|
|
expectMsg(0)
|
|
|
|
|
expectMsg(1)
|
|
|
|
|
expectMsg(2)
|
|
|
|
|
}
|
2014-12-11 14:57:48 +01:00
|
|
|
}
|