From 52864ffb28ad7ac0d0a8118b2bf8ca3e8d2532f0 Mon Sep 17 00:00:00 2001 From: Richard Imaoka Date: Sat, 28 Jul 2018 23:52:51 +0900 Subject: [PATCH] Add the pipe pattern section (#23948) --- akka-docs/src/main/paradox/futures.md | 75 +++++++++- .../main/paradox/images/futures-pipeto1.png | Bin 0 -> 26110 bytes .../main/paradox/images/futures-pipeto2.png | Bin 0 -> 28043 bytes .../test/java/jdocs/future/FutureDocTest.java | 128 +++++++++++++++++- .../scala/docs/future/FutureDocSpec.scala | 97 ++++++++++++- 5 files changed, 284 insertions(+), 16 deletions(-) create mode 100644 akka-docs/src/main/paradox/images/futures-pipeto1.png create mode 100644 akka-docs/src/main/paradox/images/futures-pipeto2.png diff --git a/akka-docs/src/main/paradox/futures.md b/akka-docs/src/main/paradox/futures.md index 2908be4df3..664d089640 100644 --- a/akka-docs/src/main/paradox/futures.md +++ b/akka-docs/src/main/paradox/futures.md @@ -91,15 +91,78 @@ When using non-blocking it is better to use the `mapTo` method to safely try to The `mapTo` method will return a new `Future` that contains the result if the cast was successful, or a `ClassCastException` if not. Handling `Exception`s will be discussed further within this documentation. -@@@ +@@@ -To send the result of a `Future` to an `Actor`, you can use the `pipe` construct: +## Use the pipe pattern -scala -: @@snip [FutureDocSpec.scala]($code$/scala/docs/future/FutureDocSpec.scala) { #pipe-to } +Another useful message-transfer pattern is "pipe", which is to send the result of `Future` to another actor, upon completion of the `Future`. +The pipe pattern can be used by importing @java[`akka.pattern.PatternsCS.pipe`.]@scala[`akka.pattern.pipe`, and define or import an implicit instance of `ExecutionContext` in the scope. -java -: @@snip [FutureDocTest.java]($code$/java/jdocs/future/FutureDocTest.java) { #pipe-to } +Scala +: @@snip [FutureDocSpec.scala]($code$/scala/docs/future/FutureDocSpec.scala) { #pipe-to-usage } + +Java +: @@snip [FutureDocTest.java]($code$/java/jdocs/future/FutureDocTest.java) { #imports-ask #imports-pipe #pipe-to-usage } + +To see how this works in more detail, let's introduce a small example consisting of three different actors, +`UserProxyActor`, `UserDataActor` and `UserActivityActor`. +In this example, when you need information about a user, you send a request message to `UserProxyActor`, +then it gets the corresponding result from the appropriate backend actor based on the request message type. + +![futures-pipeto1](images/futures-pipeto1.png) + +![futures-pipeto2](images/futures-pipeto2.png) + +The message types you send to `UserProxyActor` are `GetUserData` and `GetUserActivities`: + +Scala +: @@snip [FutureDocSpec.scala]($code$/scala/docs/future/FutureDocSpec.scala) { #pipe-to-proxy-messages } + +Java +: @@snip [FutureDocTest.java]($code$/java/jdocs/future/FutureDocTest.java) { #pipe-to-proxy-messages } + +and `UserData` and @scala[`List[UserActivity]`]@java[`ArrayList`] are returned to the original sender in the end. + +Scala +: @@snip [FutureDocSpec.scala]($code$/scala/docs/future/FutureDocSpec.scala) { #pipe-to-returned-data } + +Java +: @@snip [FutureDocTest.java]($code$/java/jdocs/future/FutureDocTest.java) { #pipe-to-returned-data } + +The backend `UserDataActor` and `UserActivityActor` are defined as follows: + +Scala +: @@snip [FutureDocSpec.scala]($code$/scala/docs/future/FutureDocSpec.scala) { #pipe-to-user-data-actor } + +Java +: @@snip [FutureDocTest.java]($code$/java/jdocs/future/FutureDocTest.java) { #pipe-to-user-data-actor } + +`UserDataActor` holds the data in memory, so that it can return the current state of the user data quickly upon a request. + +On the other hand, `UserActivityActor` queries into a `repository` to retrieve historical user activities then +sends the result to the `sender()` which is `UserProxy` in this case, with the pipe pattern. + +Scala +: @@snip [FutureDocSpec.scala]($code$/scala/docs/future/FutureDocSpec.scala) { #pipe-to-user-activity-actor } + +Java +: @@snip [FutureDocTest.java]($code$/java/jdocs/future/FutureDocTest.java) { #imports-pipe #pipe-to-user-activity-actor } + +Since it needs to talk to the separate `repository`, it takes time to retrieve the list of `UserActivity`, +hence the return type of `queryHistoricalActivities` is @scala[`Future`]@java[`CompletableFuture`]. +To send back the result to the `sender()` we used the @scala[`pipeTo`]@java[`pipe`] method, +so that the result of the @scala[`Future`]@java[`CompletableFuture`] is sent to `sender()` upon @scala[`Future`]@java[`CompletableFuture`]'s completion. + +Finally, the definition of `UserProxyActor` is as below. + +Scala +: @@snip [FutureDocSpec.scala]($code$/scala/docs/future/FutureDocSpec.scala) { #pipe-to-proxy-actor } + +Java +: @@snip [FutureDocTest.java]($code$/java/jdocs/future/FutureDocTest.java) { #imports-ask #imports-pipe #pipe-to-proxy-actor } + +Note that the @scala[`pipeTo`]@java[`pipe`] method used with the @scala[`?`]@java[`ask`] method. +Using @scala[`pipeTo`]@java[`pipe`] with the @scala[`?`]@java[`ask`] method is a common practice when you want to relay a message from one actor to another. ## Use Directly diff --git a/akka-docs/src/main/paradox/images/futures-pipeto1.png b/akka-docs/src/main/paradox/images/futures-pipeto1.png new file mode 100644 index 0000000000000000000000000000000000000000..aa8258b1105561677a92d1a05040edc7a27c2d12 GIT binary patch literal 26110 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 UerI)nE=OVTboFyt=akR{0CTTePyhe` literal 0 HcmV?d00001 diff --git a/akka-docs/src/main/paradox/images/futures-pipeto2.png b/akka-docs/src/main/paradox/images/futures-pipeto2.png new file mode 100644 index 0000000000000000000000000000000000000000..5d4fae5426f2ba042ef8c4ea8a4080738ac5ea7c GIT binary patch literal 28043 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 literal 0 HcmV?d00001 diff --git a/akka-docs/src/test/java/jdocs/future/FutureDocTest.java b/akka-docs/src/test/java/jdocs/future/FutureDocTest.java index 1b5c4886f9..4324861ec2 100644 --- a/akka-docs/src/test/java/jdocs/future/FutureDocTest.java +++ b/akka-docs/src/test/java/jdocs/future/FutureDocTest.java @@ -68,6 +68,14 @@ import static akka.pattern.PatternsCS.retry; //#imports8 +//#imports-ask +import static akka.pattern.PatternsCS.ask; +//#imports-ask +//#imports-pipe +import static akka.pattern.PatternsCS.pipe; +//#imports-pipe + + import java.util.ArrayList; import java.util.List; @@ -112,6 +120,122 @@ public class FutureDocTest extends AbstractJavaTest { } //#print-result } + + //#pipe-to-usage + public class ActorUsingPipeTo extends AbstractActor { + ActorRef target; + Timeout timeout; + + ActorUsingPipeTo(ActorRef target) { + this.target = target; + this.timeout = new Timeout(Duration.create(5, "seconds")); + } + + @Override + public Receive createReceive() { + return receiveBuilder() + .match(String.class, msg -> { + CompletableFuture fut = + ask(target, "some message", timeout).toCompletableFuture(); + + // the pipe pattern + pipe(fut, getContext().dispatcher()).to(sender()); + }) + .build(); + } + } + //#pipe-to-usage + + //#pipe-to-returned-data + public class UserData { final String data; UserData(String data){ this.data = data; } } + public class UserActivity { final String activity; UserActivity(String activity){ this.activity = activity; } } + //#pipe-to-returned-data + + //#pipe-to-user-data-actor + public class UserDataActor extends AbstractActor { + UserData internalData; + + UserDataActor(){ + this.internalData = new UserData("initial data"); + } + + @Override + public Receive createReceive() { + return receiveBuilder() + .match(GetFromUserDataActor.class, msg -> sender().tell(internalData, self())) + .build(); + } + } + + public class GetFromUserDataActor {} + //#pipe-to-user-data-actor + + //#pipe-to-user-activity-actor + interface UserActivityRepository { + CompletableFuture> queryHistoricalActivities(String userId); + } + + public class UserActivityActor extends AbstractActor { + String userId; + UserActivityRepository repository; + + UserActivityActor(String userId, UserActivityRepository repository) { + this.userId = userId; + this.repository = repository; + } + + @Override + public Receive createReceive() { + return receiveBuilder() + .match(GetFromUserActivityActor.class, msg -> { + CompletableFuture> fut = + repository.queryHistoricalActivities(userId); + + pipe(fut, getContext().dispatcher()).to(sender()); + }) + .build(); + } + } + + public class GetFromUserActivityActor {} + //#pipe-to-user-activity-actor + + //#pipe-to-proxy-actor + public class UserProxyActor extends AbstractActor { + ActorRef userActor; + ActorRef userActivityActor; + Timeout timeout = new Timeout(Duration.create(5, "seconds")); + + UserProxyActor(ActorRef userActor, ActorRef userActivityActor) { + this.userActor = userActor; + this.userActivityActor = userActivityActor; + } + + @Override + public Receive createReceive() { + return receiveBuilder() + .match(GetUserData.class, msg -> { + CompletableFuture fut = + ask(userActor, new GetUserData(), timeout).toCompletableFuture(); + + pipe(fut, getContext().dispatcher()); + }) + .match(GetUserActivities.class, msg -> { + CompletableFuture fut = + ask(userActivityActor, new GetFromUserActivityActor(), timeout).toCompletableFuture(); + + pipe(fut, getContext().dispatcher()).to(sender()); + }) + .build(); + } + } + //#pipe-to-proxy-actor + + //#pipe-to-proxy-messages + public class GetUserData {} + public class GetUserActivities {} + //#pipe-to-proxy-messages + @SuppressWarnings("unchecked") @Test public void useCustomExecutionContext() throws Exception { ExecutorService yourExecutorServiceGoesHere = Executors.newSingleThreadExecutor(); //#diy-execution-context @@ -135,9 +259,7 @@ public class FutureDocTest extends AbstractJavaTest { Future future = Patterns.ask(actor, msg, timeout); String result = (String) Await.result(future, timeout.duration()); //#ask-blocking - //#pipe-to - akka.pattern.Patterns.pipe(future, system.dispatcher()).to(actor); - //#pipe-to + assertEquals("HELLO", result); } diff --git a/akka-docs/src/test/scala/docs/future/FutureDocSpec.scala b/akka-docs/src/test/scala/docs/future/FutureDocSpec.scala index 8c962346a5..f30009f7c7 100644 --- a/akka-docs/src/test/scala/docs/future/FutureDocSpec.scala +++ b/akka-docs/src/test/scala/docs/future/FutureDocSpec.scala @@ -7,8 +7,7 @@ package docs.future import language.postfixOps import akka.testkit._ -import akka.actor.{ Actor, Props } -import akka.actor.Status +import akka.actor.{ Actor, ActorRef, Props, Status } import akka.util.Timeout import scala.concurrent.duration._ import java.lang.IllegalStateException @@ -35,6 +34,95 @@ object FutureDocSpec { n += 2 } } + + //#pipe-to-usage + class ActorUsingPipeTo(target: ActorRef) extends Actor { + // akka.pattern.pipe needs to be imported + import akka.pattern.{ask, pipe} + // implicit ExecutionContext should be in scope + implicit val ec: ExecutionContext = context.dispatcher + + def receive = { + val future = target ? "some message" + future pipeTo sender() // use the pipe pattern + } + } + //#pipe-to-usage + + //#pipe-to-returned-data + case class UserData(data: String) + case class UserActivity(activity: String) + //#pipe-to-returned-data + + //#pipe-to-user-data-actor + class UserDataActor extends Actor { + import UserDataActor._ + + //holds the user data internally + var internalData: UserData = UserData("initial data") + + def receive = { + case Get ⇒ + sender() ! internalData + } + } + + object UserDataActor { + case object Get + } + //#pipe-to-user-data-actor + + //#pipe-to-user-activity-actor + trait UserActivityRepository { + def queryHistoricalActivities(userId: String): Future[List[UserActivity]] + } + + class UserActivityActor(val userId: String, repository: UserActivityRepository) extends Actor { + import akka.pattern.pipe + import UserActivityActor._ + implicit val ec: ExecutionContext = context.dispatcher + + def receive = { + case Get ⇒ + // user's historical activities are retrieved + // via the separate repository + repository.queryHistoricalActivities(userId) pipeTo sender() + } + } + + object UserActivityActor { + case object Get + } + //#pipe-to-user-activity-actor + + //#pipe-to-proxy-actor + class UserProxyActor( + userData: ActorRef, + userActivities: ActorRef + ) extends Actor { + import UserProxyActor._ + import akka.pattern.{ ask, pipe } + implicit val ec: ExecutionContext = context.dispatcher + + implicit val timeout = Timeout(5 seconds) + + def receive = { + case GetUserData ⇒ + (userData ? UserDataActor.Get) pipeTo sender() + case GetUserActivities ⇒ + (userActivities ? UserActivityActor.Get) pipeTo sender() + } + } + //#pipe-to-proxy-actor + + //#pipe-to-proxy-messages + object UserProxyActor { + sealed trait Message + case object GetUserData extends Message + case object GetUserActivities extends Message + } + //#pipe-to-proxy-messages + } class FutureDocSpec extends AkkaSpec { @@ -73,11 +161,6 @@ class FutureDocSpec extends AkkaSpec { val result = Await.result(future, timeout.duration).asInstanceOf[String] //#ask-blocking - //#pipe-to - import akka.pattern.pipe - future pipeTo actor - //#pipe-to - result should be("HELLO") }