2018-10-29 17:19:37 +08:00
|
|
|
/*
|
2019-01-02 18:55:26 +08:00
|
|
|
* Copyright (C) 2015-2019 Lightbend Inc. <https://www.lightbend.com>
|
2015-02-04 09:26:32 +01:00
|
|
|
*/
|
2018-03-13 23:45:55 +09:00
|
|
|
|
2015-02-04 09:26:32 +01:00
|
|
|
package docs.stream
|
|
|
|
|
|
|
|
|
|
import scala.concurrent.Await
|
2015-06-23 18:28:53 +02:00
|
|
|
import akka.stream.ActorMaterializer
|
|
|
|
|
import akka.stream.ActorMaterializerSettings
|
2015-02-04 09:26:32 +01:00
|
|
|
import akka.stream.Supervision
|
|
|
|
|
import akka.stream.scaladsl._
|
2016-02-25 14:27:45 +01:00
|
|
|
import akka.testkit.AkkaSpec
|
2015-06-23 17:32:55 +02:00
|
|
|
import akka.stream.Attributes
|
|
|
|
|
import akka.stream.ActorAttributes
|
2015-05-21 16:03:10 +02:00
|
|
|
import scala.concurrent.duration._
|
2015-02-04 09:26:32 +01:00
|
|
|
|
|
|
|
|
class FlowErrorDocSpec extends AkkaSpec {
|
|
|
|
|
|
|
|
|
|
"demonstrate fail stream" in {
|
|
|
|
|
//#stop
|
2015-12-11 14:45:24 +01:00
|
|
|
implicit val materializer = ActorMaterializer()
|
2015-02-04 09:26:32 +01:00
|
|
|
val source = Source(0 to 5).map(100 / _)
|
|
|
|
|
val result = source.runWith(Sink.fold(0)(_ + _))
|
|
|
|
|
// division by zero will fail the stream and the
|
|
|
|
|
// result here will be a Future completed with Failure(ArithmeticException)
|
|
|
|
|
//#stop
|
|
|
|
|
|
|
|
|
|
intercept[ArithmeticException] {
|
2015-05-21 16:03:10 +02:00
|
|
|
Await.result(result, 3.seconds)
|
2015-02-04 09:26:32 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"demonstrate resume stream" in {
|
|
|
|
|
//#resume
|
2015-03-06 12:15:20 +01:00
|
|
|
val decider: Supervision.Decider = {
|
2019-02-09 15:25:39 +01:00
|
|
|
case _: ArithmeticException => Supervision.Resume
|
|
|
|
|
case _ => Supervision.Stop
|
2015-02-04 09:26:32 +01:00
|
|
|
}
|
2019-03-11 10:38:24 +01:00
|
|
|
implicit val materializer = ActorMaterializer(ActorMaterializerSettings(system).withSupervisionStrategy(decider))
|
2015-02-04 09:26:32 +01:00
|
|
|
val source = Source(0 to 5).map(100 / _)
|
|
|
|
|
val result = source.runWith(Sink.fold(0)(_ + _))
|
|
|
|
|
// the element causing division by zero will be dropped
|
|
|
|
|
// result here will be a Future completed with Success(228)
|
|
|
|
|
//#resume
|
|
|
|
|
|
2015-05-21 16:03:10 +02:00
|
|
|
Await.result(result, 3.seconds) should be(228)
|
2015-02-04 09:26:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"demonstrate resume section" in {
|
|
|
|
|
//#resume-section
|
2015-12-11 14:45:24 +01:00
|
|
|
implicit val materializer = ActorMaterializer()
|
2015-03-06 12:15:20 +01:00
|
|
|
val decider: Supervision.Decider = {
|
2019-02-09 15:25:39 +01:00
|
|
|
case _: ArithmeticException => Supervision.Resume
|
|
|
|
|
case _ => Supervision.Stop
|
2015-02-04 09:26:32 +01:00
|
|
|
}
|
2015-04-09 15:16:59 +02:00
|
|
|
val flow = Flow[Int]
|
2019-03-11 10:38:24 +01:00
|
|
|
.filter(100 / _ < 50)
|
|
|
|
|
.map(elem => 100 / (5 - elem))
|
2015-06-23 17:32:55 +02:00
|
|
|
.withAttributes(ActorAttributes.supervisionStrategy(decider))
|
2015-04-09 15:16:59 +02:00
|
|
|
val source = Source(0 to 5).via(flow)
|
|
|
|
|
|
2015-02-04 09:26:32 +01:00
|
|
|
val result = source.runWith(Sink.fold(0)(_ + _))
|
|
|
|
|
// the elements causing division by zero will be dropped
|
|
|
|
|
// result here will be a Future completed with Success(150)
|
|
|
|
|
//#resume-section
|
|
|
|
|
|
2015-05-21 16:03:10 +02:00
|
|
|
Await.result(result, 3.seconds) should be(150)
|
2015-02-04 09:26:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"demonstrate restart section" in {
|
|
|
|
|
//#restart-section
|
2015-12-11 14:45:24 +01:00
|
|
|
implicit val materializer = ActorMaterializer()
|
2015-03-06 12:15:20 +01:00
|
|
|
val decider: Supervision.Decider = {
|
2019-02-09 15:25:39 +01:00
|
|
|
case _: IllegalArgumentException => Supervision.Restart
|
|
|
|
|
case _ => Supervision.Stop
|
2015-02-04 09:26:32 +01:00
|
|
|
}
|
2015-04-09 15:16:59 +02:00
|
|
|
val flow = Flow[Int]
|
2019-02-09 15:25:39 +01:00
|
|
|
.scan(0) { (acc, elem) =>
|
2015-04-09 15:16:59 +02:00
|
|
|
if (elem < 0) throw new IllegalArgumentException("negative not allowed")
|
|
|
|
|
else acc + elem
|
2015-02-04 09:26:32 +01:00
|
|
|
}
|
2015-06-23 17:32:55 +02:00
|
|
|
.withAttributes(ActorAttributes.supervisionStrategy(decider))
|
2015-04-09 15:16:59 +02:00
|
|
|
val source = Source(List(1, 3, -1, 5, 7)).via(flow)
|
2016-02-12 01:36:21 +08:00
|
|
|
val result = source.limit(1000).runWith(Sink.seq)
|
2015-02-04 09:26:32 +01:00
|
|
|
// the negative element cause the scan stage to be restarted,
|
|
|
|
|
// i.e. start from 0 again
|
2015-04-20 16:33:57 +02:00
|
|
|
// result here will be a Future completed with Success(Vector(0, 1, 4, 0, 5, 12))
|
2015-02-04 09:26:32 +01:00
|
|
|
//#restart-section
|
|
|
|
|
|
2015-05-21 16:03:10 +02:00
|
|
|
Await.result(result, 3.seconds) should be(Vector(0, 1, 4, 0, 5, 12))
|
2015-02-04 09:26:32 +01:00
|
|
|
}
|
|
|
|
|
|
2017-07-26 16:23:46 +02:00
|
|
|
"demonstrate recover" in {
|
|
|
|
|
implicit val materializer = ActorMaterializer()
|
|
|
|
|
//#recover
|
2019-03-11 10:38:24 +01:00
|
|
|
Source(0 to 6)
|
|
|
|
|
.map(n =>
|
|
|
|
|
if (n < 5) n.toString
|
|
|
|
|
else throw new RuntimeException("Boom!"))
|
|
|
|
|
.recover {
|
|
|
|
|
case _: RuntimeException => "stream truncated"
|
|
|
|
|
}
|
|
|
|
|
.runForeach(println)
|
2017-07-26 16:23:46 +02:00
|
|
|
//#recover
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Output:
|
|
|
|
|
//#recover-output
|
|
|
|
|
0
|
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
|
|
4
|
|
|
|
|
stream truncated
|
|
|
|
|
//#recover-output
|
2019-03-11 10:38:24 +01:00
|
|
|
*/
|
2017-07-26 16:23:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"demonstrate recoverWithRetries" in {
|
|
|
|
|
implicit val materializer = ActorMaterializer()
|
|
|
|
|
//#recoverWithRetries
|
|
|
|
|
val planB = Source(List("five", "six", "seven", "eight"))
|
|
|
|
|
|
2019-03-11 10:38:24 +01:00
|
|
|
Source(0 to 10)
|
|
|
|
|
.map(n =>
|
|
|
|
|
if (n < 5) n.toString
|
|
|
|
|
else throw new RuntimeException("Boom!"))
|
|
|
|
|
.recoverWithRetries(attempts = 1, {
|
|
|
|
|
case _: RuntimeException => planB
|
|
|
|
|
})
|
|
|
|
|
.runForeach(println)
|
2017-07-26 16:23:46 +02:00
|
|
|
//#recoverWithRetries
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Output:
|
|
|
|
|
//#recoverWithRetries-output
|
|
|
|
|
0
|
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
|
|
4
|
|
|
|
|
five
|
|
|
|
|
six
|
|
|
|
|
seven
|
|
|
|
|
eight
|
|
|
|
|
//#recoverWithRetries-output
|
2019-03-11 10:38:24 +01:00
|
|
|
*/
|
2017-07-26 16:23:46 +02:00
|
|
|
}
|
|
|
|
|
|
2015-02-04 09:26:32 +01:00
|
|
|
}
|