2014-12-11 14:57:48 +01:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2014 Typesafe Inc. <http://www.typesafe.com>
|
|
|
|
|
*/
|
|
|
|
|
package docs.stream
|
|
|
|
|
|
2015-01-27 18:29:20 +01:00
|
|
|
import akka.stream.ActorFlowMaterializer
|
2014-12-11 14:57:48 +01:00
|
|
|
import akka.stream.scaladsl.Broadcast
|
|
|
|
|
import akka.stream.scaladsl.Flow
|
|
|
|
|
import akka.stream.scaladsl.FlowGraph
|
|
|
|
|
import akka.stream.scaladsl.FlowGraphImplicits
|
2014-12-11 14:57:48 +01:00
|
|
|
import akka.stream.scaladsl.PartialFlowGraph
|
2014-12-11 14:57:48 +01:00
|
|
|
import akka.stream.scaladsl.Sink
|
|
|
|
|
import akka.stream.scaladsl.Source
|
|
|
|
|
import akka.stream.scaladsl.UndefinedSink
|
|
|
|
|
import akka.stream.scaladsl.UndefinedSource
|
|
|
|
|
import akka.stream.scaladsl.Zip
|
|
|
|
|
import akka.stream.scaladsl.ZipWith
|
2014-12-11 14:57:48 +01:00
|
|
|
import akka.stream.testkit.AkkaSpec
|
|
|
|
|
|
2014-12-11 14:57:48 +01:00
|
|
|
import scala.concurrent.Await
|
|
|
|
|
import scala.concurrent.Future
|
|
|
|
|
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-01-27 18:29:20 +01:00
|
|
|
implicit val mat = ActorFlowMaterializer()
|
2014-12-11 14:57:48 +01:00
|
|
|
|
|
|
|
|
"build with open ports" in {
|
2014-12-11 14:57:48 +01:00
|
|
|
// format: OFF
|
2014-12-11 14:57:48 +01:00
|
|
|
//#simple-partial-flow-graph
|
2014-12-11 14:57:48 +01:00
|
|
|
// defined outside as they will be used by different FlowGraphs
|
|
|
|
|
// 1) first by the PartialFlowGraph to mark its open input and output ports
|
|
|
|
|
// 2) then by the assembling FlowGraph which will attach real sinks and sources to them
|
|
|
|
|
val in1 = UndefinedSource[Int]
|
|
|
|
|
val in2 = UndefinedSource[Int]
|
|
|
|
|
val in3 = UndefinedSource[Int]
|
|
|
|
|
val out = UndefinedSink[Int]
|
|
|
|
|
|
2014-12-22 16:18:26 +01:00
|
|
|
val pickMaxOfThree: PartialFlowGraph = PartialFlowGraph { implicit b =>
|
2014-12-11 14:57:48 +01:00
|
|
|
import FlowGraphImplicits._
|
2014-12-11 14:57:48 +01:00
|
|
|
|
2014-12-11 14:57:48 +01:00
|
|
|
val zip1 = ZipWith[Int, Int, Int](math.max _)
|
|
|
|
|
val zip2 = ZipWith[Int, Int, Int](math.max _)
|
|
|
|
|
|
|
|
|
|
in1 ~> zip1.left
|
|
|
|
|
in2 ~> zip1.right
|
|
|
|
|
zip1.out ~> zip2.left
|
|
|
|
|
in3 ~> zip2.right
|
|
|
|
|
zip2.out ~> out
|
2014-12-11 14:57:48 +01:00
|
|
|
}
|
2014-12-18 18:11:32 +01:00
|
|
|
//#simple-partial-flow-graph
|
2014-12-11 14:57:48 +01:00
|
|
|
// format: ON
|
2014-12-18 18:11:32 +01:00
|
|
|
//#simple-partial-flow-graph
|
2014-12-11 14:57:48 +01:00
|
|
|
|
|
|
|
|
val resultSink = Sink.head[Int]
|
|
|
|
|
|
2014-12-22 16:18:26 +01:00
|
|
|
val g = FlowGraph { b =>
|
2014-12-11 14:57:48 +01:00
|
|
|
// import the partial flow graph explicitly
|
|
|
|
|
b.importPartialFlowGraph(pickMaxOfThree)
|
|
|
|
|
|
|
|
|
|
b.attachSource(in1, Source.single(1))
|
|
|
|
|
b.attachSource(in2, Source.single(2))
|
|
|
|
|
b.attachSource(in3, Source.single(3))
|
|
|
|
|
b.attachSink(out, resultSink)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val materialized = g.run()
|
|
|
|
|
val max: Future[Int] = materialized.get(resultSink)
|
|
|
|
|
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
|
|
|
|
|
|
|
|
val g2 =
|
|
|
|
|
//#simple-partial-flow-graph-import-shorthand
|
2014-12-22 16:18:26 +01:00
|
|
|
FlowGraph(pickMaxOfThree) { b =>
|
2014-12-11 14:57:48 +01:00
|
|
|
b.attachSource(in1, Source.single(1))
|
|
|
|
|
b.attachSource(in2, Source.single(2))
|
|
|
|
|
b.attachSource(in3, Source.single(3))
|
|
|
|
|
b.attachSink(out, resultSink)
|
|
|
|
|
}
|
|
|
|
|
//#simple-partial-flow-graph-import-shorthand
|
|
|
|
|
val materialized2 = g.run()
|
|
|
|
|
val max2: Future[Int] = materialized2.get(resultSink)
|
|
|
|
|
Await.result(max2, 300.millis) should equal(3)
|
2014-12-11 14:57:48 +01:00
|
|
|
}
|
|
|
|
|
|
2014-12-11 14:57:48 +01:00
|
|
|
"build source from partial flow graph" in {
|
|
|
|
|
//#source-from-partial-flow-graph
|
2014-12-22 16:18:26 +01:00
|
|
|
val pairs: Source[(Int, Int)] = Source() { implicit b =>
|
2014-12-11 14:57:48 +01:00
|
|
|
import FlowGraphImplicits._
|
|
|
|
|
|
|
|
|
|
// prepare graph elements
|
|
|
|
|
val undefinedSink = UndefinedSink[(Int, Int)]
|
|
|
|
|
val zip = 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
|
|
|
|
|
ints ~> Flow[Int].filter(_ % 2 != 0) ~> zip.left
|
|
|
|
|
ints ~> Flow[Int].filter(_ % 2 == 0) ~> zip.right
|
|
|
|
|
zip.out ~> undefinedSink
|
|
|
|
|
|
|
|
|
|
// expose undefined sink
|
|
|
|
|
undefinedSink
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val firstPair: Future[(Int, Int)] = pairs.runWith(Sink.head)
|
|
|
|
|
//#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
|
2014-12-22 16:18:26 +01:00
|
|
|
val pairUpWithToString = Flow() { implicit b =>
|
2014-12-11 14:57:48 +01:00
|
|
|
import FlowGraphImplicits._
|
|
|
|
|
|
|
|
|
|
// prepare graph elements
|
|
|
|
|
val undefinedSource = UndefinedSource[Int]
|
|
|
|
|
val undefinedSink = UndefinedSink[(Int, String)]
|
|
|
|
|
|
|
|
|
|
val broadcast = Broadcast[Int]
|
|
|
|
|
val zip = Zip[Int, String]
|
|
|
|
|
|
|
|
|
|
// connect the graph
|
|
|
|
|
undefinedSource ~> broadcast
|
|
|
|
|
broadcast ~> Flow[Int].map(identity) ~> zip.left
|
|
|
|
|
broadcast ~> Flow[Int].map(_.toString) ~> zip.right
|
|
|
|
|
zip.out ~> undefinedSink
|
|
|
|
|
|
|
|
|
|
// expose undefined ports
|
|
|
|
|
(undefinedSource, undefinedSink)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//#flow-from-partial-flow-graph
|
|
|
|
|
|
|
|
|
|
// format: OFF
|
|
|
|
|
val (_, matSink: Future[(Int, String)]) =
|
|
|
|
|
//#flow-from-partial-flow-graph
|
|
|
|
|
pairUpWithToString.runWith(Source(List(1)), Sink.head)
|
|
|
|
|
//#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
|
|
|
}
|
2014-12-11 14:57:48 +01:00
|
|
|
}
|