2014-12-18 14:55:15 +01:00
|
|
|
package docs.stream
|
|
|
|
|
|
2015-10-21 22:45:39 +02:00
|
|
|
import akka.stream.{ ClosedShape, OverflowStrategy, ActorMaterializer }
|
2014-12-18 14:55:15 +01:00
|
|
|
import akka.stream.scaladsl._
|
|
|
|
|
import akka.stream.testkit.AkkaSpec
|
|
|
|
|
|
|
|
|
|
class GraphCyclesSpec extends AkkaSpec {
|
|
|
|
|
|
2015-12-11 14:45:24 +01:00
|
|
|
implicit val materializer = ActorMaterializer()
|
2014-12-18 14:55:15 +01:00
|
|
|
|
|
|
|
|
"Cycle demonstration" must {
|
2015-12-17 11:48:30 +02:00
|
|
|
val source = Source.fromIterator(() => Iterator.from(0))
|
2014-12-18 14:55:15 +01:00
|
|
|
|
|
|
|
|
"include a deadlocked cycle" in {
|
|
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: OFF
|
2014-12-18 14:55:15 +01:00
|
|
|
//#deadlocked
|
|
|
|
|
// WARNING! The graph below deadlocks!
|
2015-11-30 15:45:37 +01:00
|
|
|
RunnableGraph.fromGraph(GraphDSL.create() { implicit b =>
|
|
|
|
|
import GraphDSL.Implicits._
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
val merge = b.add(Merge[Int](2))
|
|
|
|
|
val bcast = b.add(Broadcast[Int](2))
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-03-05 12:21:17 +01:00
|
|
|
source ~> merge ~> Flow[Int].map { s => println(s); s } ~> bcast ~> Sink.ignore
|
2015-01-28 14:19:50 +01:00
|
|
|
merge <~ bcast
|
2015-10-21 22:45:39 +02:00
|
|
|
ClosedShape
|
|
|
|
|
})
|
2014-12-18 14:55:15 +01:00
|
|
|
//#deadlocked
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: ON
|
2014-12-18 14:55:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"include an unfair cycle" in {
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: OFF
|
2014-12-18 14:55:15 +01:00
|
|
|
//#unfair
|
|
|
|
|
// WARNING! The graph below stops consuming from "source" after a few steps
|
2015-11-30 15:45:37 +01:00
|
|
|
RunnableGraph.fromGraph(GraphDSL.create() { implicit b =>
|
|
|
|
|
import GraphDSL.Implicits._
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
val merge = b.add(MergePreferred[Int](1))
|
|
|
|
|
val bcast = b.add(Broadcast[Int](2))
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-03-05 12:21:17 +01:00
|
|
|
source ~> merge ~> Flow[Int].map { s => println(s); s } ~> bcast ~> Sink.ignore
|
2015-01-28 14:19:50 +01:00
|
|
|
merge.preferred <~ bcast
|
2015-10-21 22:45:39 +02:00
|
|
|
ClosedShape
|
|
|
|
|
})
|
2014-12-18 14:55:15 +01:00
|
|
|
//#unfair
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: ON
|
2014-12-18 14:55:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"include a dropping cycle" in {
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: OFF
|
2014-12-18 14:55:15 +01:00
|
|
|
//#dropping
|
2015-11-30 15:45:37 +01:00
|
|
|
RunnableGraph.fromGraph(GraphDSL.create() { implicit b =>
|
|
|
|
|
import GraphDSL.Implicits._
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
val merge = b.add(Merge[Int](2))
|
|
|
|
|
val bcast = b.add(Broadcast[Int](2))
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-03-05 12:21:17 +01:00
|
|
|
source ~> merge ~> Flow[Int].map { s => println(s); s } ~> bcast ~> Sink.ignore
|
2015-01-28 14:19:50 +01:00
|
|
|
merge <~ Flow[Int].buffer(10, OverflowStrategy.dropHead) <~ bcast
|
2015-10-21 22:45:39 +02:00
|
|
|
ClosedShape
|
|
|
|
|
})
|
2014-12-18 14:55:15 +01:00
|
|
|
//#dropping
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: ON
|
2014-12-18 14:55:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"include a dead zipping cycle" in {
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: OFF
|
2014-12-18 14:55:15 +01:00
|
|
|
//#zipping-dead
|
|
|
|
|
// WARNING! The graph below never processes any elements
|
2015-11-30 15:45:37 +01:00
|
|
|
RunnableGraph.fromGraph(GraphDSL.create() { implicit b =>
|
|
|
|
|
import GraphDSL.Implicits._
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
val zip = b.add(ZipWith[Int, Int, Int]((left, right) => right))
|
|
|
|
|
val bcast = b.add(Broadcast[Int](2))
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
source ~> zip.in0
|
2015-03-05 12:21:17 +01:00
|
|
|
zip.out.map { s => println(s); s } ~> bcast ~> Sink.ignore
|
2015-01-28 14:19:50 +01:00
|
|
|
zip.in1 <~ bcast
|
2015-10-21 22:45:39 +02:00
|
|
|
ClosedShape
|
|
|
|
|
})
|
2014-12-18 14:55:15 +01:00
|
|
|
//#zipping-dead
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: ON
|
2014-12-18 14:55:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"include a live zipping cycle" in {
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: OFF
|
2014-12-18 14:55:15 +01:00
|
|
|
//#zipping-live
|
2015-11-30 15:45:37 +01:00
|
|
|
RunnableGraph.fromGraph(GraphDSL.create() { implicit b =>
|
|
|
|
|
import GraphDSL.Implicits._
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
val zip = b.add(ZipWith((left: Int, right: Int) => left))
|
|
|
|
|
val bcast = b.add(Broadcast[Int](2))
|
|
|
|
|
val concat = b.add(Concat[Int]())
|
2015-02-26 16:37:16 +01:00
|
|
|
val start = Source.single(0)
|
2014-12-18 14:55:15 +01:00
|
|
|
|
2015-01-28 14:19:50 +01:00
|
|
|
source ~> zip.in0
|
2015-03-05 12:21:17 +01:00
|
|
|
zip.out.map { s => println(s); s } ~> bcast ~> Sink.ignore
|
2015-02-26 16:37:16 +01:00
|
|
|
zip.in1 <~ concat <~ start
|
|
|
|
|
concat <~ bcast
|
2015-10-21 22:45:39 +02:00
|
|
|
ClosedShape
|
|
|
|
|
})
|
2014-12-18 14:55:15 +01:00
|
|
|
//#zipping-live
|
2015-01-28 14:19:50 +01:00
|
|
|
// format: ON
|
2014-12-18 14:55:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|