improve streams actor integration docs, #21698 (#21700)

* mapAsync + ask should be the first choice
* add missing Source.queue
* prefer actorRefWithAck
* move ActorPublisher and ActorSubscriber to the end
  with additional warning
* fix wrong doc of SourceQueue offer
* and add missing java api
This commit is contained in:
Patrik Nordwall 2016-10-26 10:24:51 +02:00 committed by GitHub
parent bcf4de5b2c
commit aa8c253d14
9 changed files with 457 additions and 232 deletions

View file

@ -15,7 +15,6 @@ import akka.actor.ActorRef
import com.typesafe.config.ConfigFactory
import akka.actor.Actor
import akka.actor.Props
import akka.pattern.ask
import akka.util.Timeout
import akka.stream.Attributes
import akka.stream.ActorAttributes
@ -24,6 +23,7 @@ import akka.stream.ActorMaterializerSettings
import java.util.concurrent.atomic.AtomicInteger
import akka.stream.Supervision
import akka.stream.scaladsl.Flow
import akka.Done
object IntegrationDocSpec {
import TwitterStreamQuickstartDocSpec._
@ -120,6 +120,17 @@ object IntegrationDocSpec {
}
//#sometimes-slow-service
//#ask-actor
class Translator extends Actor {
def receive = {
case word: String =>
// ... process message
val reply = word.toUpperCase
sender() ! reply // reply to the ask
}
}
//#ask-actor
}
class IntegrationDocSpec extends AkkaSpec(IntegrationDocSpec.config) {
@ -127,6 +138,22 @@ class IntegrationDocSpec extends AkkaSpec(IntegrationDocSpec.config) {
import IntegrationDocSpec._
implicit val materializer = ActorMaterializer()
val ref: ActorRef = system.actorOf(Props[Translator])
"mapAsync + ask" in {
//#mapAsync-ask
import akka.pattern.ask
implicit val askTimeout = Timeout(5.seconds)
val words: Source[String, NotUsed] =
Source(List("hello", "hi"))
words
.mapAsync(parallelism = 5)(elem => (ref ? elem).mapTo[String])
// continue processing of the replies from the actor
.map(_.toLowerCase)
.runWith(Sink.ignore)
//#mapAsync-ask
}
"calling external service with mapAsync" in {
val probe = TestProbe()
@ -136,7 +163,7 @@ class IntegrationDocSpec extends AkkaSpec(IntegrationDocSpec.config) {
//#tweet-authors
val authors: Source[Author, NotUsed] =
tweets
.filter(_.hashtags.contains(akka))
.filter(_.hashtags.contains(akkaTag))
.map(_.author)
//#tweet-authors
@ -171,7 +198,7 @@ class IntegrationDocSpec extends AkkaSpec(IntegrationDocSpec.config) {
"lookup email with mapAsync and supervision" in {
val addressSystem = new AddressSystem2
val authors: Source[Author, NotUsed] =
tweets.filter(_.hashtags.contains(akka)).map(_.author)
tweets.filter(_.hashtags.contains(akkaTag)).map(_.author)
//#email-addresses-mapAsync-supervision
import ActorAttributes.supervisionStrategy
@ -191,7 +218,7 @@ class IntegrationDocSpec extends AkkaSpec(IntegrationDocSpec.config) {
//#external-service-mapAsyncUnordered
val authors: Source[Author, NotUsed] =
tweets.filter(_.hashtags.contains(akka)).map(_.author)
tweets.filter(_.hashtags.contains(akkaTag)).map(_.author)
val emailAddresses: Source[String, NotUsed] =
authors
@ -224,7 +251,7 @@ class IntegrationDocSpec extends AkkaSpec(IntegrationDocSpec.config) {
val addressSystem = new AddressSystem
val smsServer = new SmsServer(probe.ref)
val authors = tweets.filter(_.hashtags.contains(akka)).map(_.author)
val authors = tweets.filter(_.hashtags.contains(akkaTag)).map(_.author)
val phoneNumbers =
authors.mapAsync(4)(author => addressSystem.lookupPhoneNumber(author.handle))
@ -261,7 +288,7 @@ class IntegrationDocSpec extends AkkaSpec(IntegrationDocSpec.config) {
val addressSystem = new AddressSystem
val smsServer = new SmsServer(probe.ref)
val authors = tweets.filter(_.hashtags.contains(akka)).map(_.author)
val authors = tweets.filter(_.hashtags.contains(akkaTag)).map(_.author)
val phoneNumbers =
authors.mapAsync(4)(author => addressSystem.lookupPhoneNumber(author.handle))
@ -293,7 +320,9 @@ class IntegrationDocSpec extends AkkaSpec(IntegrationDocSpec.config) {
val database = system.actorOf(Props(classOf[DatabaseService], probe.ref), "db")
//#save-tweets
val akkaTweets: Source[Tweet, NotUsed] = tweets.filter(_.hashtags.contains(akka))
import akka.pattern.ask
val akkaTweets: Source[Tweet, NotUsed] = tweets.filter(_.hashtags.contains(akkaTag))
implicit val timeout = Timeout(3.seconds)
val saveTweets: RunnableGraph[NotUsed] =

View file

@ -23,7 +23,7 @@ class ReactiveStreamsDocSpec extends AkkaSpec {
trait Fixture {
//#authors
val authors = Flow[Tweet]
.filter(_.hashtags.contains(akka))
.filter(_.hashtags.contains(akkaTag))
.map(_.author)
//#authors

View file

@ -28,7 +28,7 @@ object TwitterStreamQuickstartDocSpec {
body.split(" ").collect { case t if t.startsWith("#") => Hashtag(t) }.toSet
}
val akka = Hashtag("#akka")
val akkaTag = Hashtag("#akka")
//#model
abstract class TweetSourceDecl {
@ -76,7 +76,7 @@ class TwitterStreamQuickstartDocSpec extends AkkaSpec {
//#authors-filter-map
val authors: Source[Author, NotUsed] =
tweets
.filter(_.hashtags.contains(akka))
.filter(_.hashtags.contains(akkaTag))
.map(_.author)
//#first-sample
//#authors-filter-map
@ -84,7 +84,7 @@ class TwitterStreamQuickstartDocSpec extends AkkaSpec {
trait Example3 {
//#authors-collect
val authors: Source[Author, NotUsed] =
tweets.collect { case t if t.hashtags.contains(akka) => t.author }
tweets.collect { case t if t.hashtags.contains(akkaTag) => t.author }
//#authors-collect
}
@ -124,7 +124,7 @@ class TwitterStreamQuickstartDocSpec extends AkkaSpec {
val bcast = b.add(Broadcast[Tweet](2))
tweets ~> bcast.in
bcast.out(0) ~> Flow[Tweet].map(_.author) ~> writeAuthors
bcast.out(0) ~> Flow[Tweet].map(_.author) ~> writeAuthors
bcast.out(1) ~> Flow[Tweet].mapConcat(_.hashtags.toList) ~> writeHashtags
ClosedShape
})
@ -192,7 +192,7 @@ class TwitterStreamQuickstartDocSpec extends AkkaSpec {
val sumSink = Sink.fold[Int, Int](0)(_ + _)
val counterRunnableGraph: RunnableGraph[Future[Int]] =
tweetsInMinuteFromNow
.filter(_.hashtags contains akka)
.filter(_.hashtags contains akkaTag)
.map(t => 1)
.toMat(sumSink)(Keep.right)