From 3fc148f6f2c510a4e37d260ca5f24eaad3f02d7c Mon Sep 17 00:00:00 2001 From: Enno <458526+ennru@users.noreply.github.com> Date: Wed, 9 Oct 2019 19:43:03 +0200 Subject: [PATCH] Typed docs: some spelling and language fixes (#27919) --- .../akka/typed/InteractionPatternsTest.java | 2 +- .../java/jdocs/akka/typed/RouterTest.java | 3 +++ .../akka/typed/InteractionPatternsSpec.scala | 2 +- .../scala/docs/akka/typed/RouterSpec.scala | 4 ++- .../src/main/scala/akka/actor/ActorRef.scala | 2 +- .../src/main/paradox/typed/actor-discovery.md | 2 +- .../src/main/paradox/typed/actor-lifecycle.md | 12 ++++----- .../src/main/paradox/typed/dispatchers.md | 24 +++++++++--------- .../paradox/typed/interaction-patterns.md | 25 +++++++++++-------- akka-docs/src/main/paradox/typed/routers.md | 6 ++--- akka-docs/src/main/paradox/typed/stash.md | 4 +-- project/Paradox.scala | 4 +-- 12 files changed, 49 insertions(+), 41 deletions(-) diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/InteractionPatternsTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/InteractionPatternsTest.java index b2b589cb60..bfa12bbc9d 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/InteractionPatternsTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/InteractionPatternsTest.java @@ -87,7 +87,7 @@ public class InteractionPatternsTest extends JUnitSuite { private static Behavior onRequest(Request request) { // ... process request ... - request.replyTo.tell(new Response("Here's the cookies for " + request.query)); + request.replyTo.tell(new Response("Here are the cookies for " + request.query)); return Behaviors.same(); } // #request-response-respond diff --git a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java index 5cce0ff211..91263946f3 100644 --- a/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java +++ b/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/RouterTest.java @@ -81,7 +81,10 @@ public class RouterTest { } static Behavior showGroupRouting() { + // #group ServiceKey serviceKey = ServiceKey.create(Worker.Command.class, "log-worker"); + + // #group return Behaviors.setup( context -> { // #group diff --git a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/InteractionPatternsSpec.scala b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/InteractionPatternsSpec.scala index aefa85ae8e..3352a7d66e 100644 --- a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/InteractionPatternsSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/InteractionPatternsSpec.scala @@ -70,7 +70,7 @@ class InteractionPatternsSpec extends ScalaTestWithActorTestKit with WordSpecLik Behaviors.receiveMessage[Request] { case Request(query, replyTo) => // ... process query ... - replyTo ! Response(s"Here's the cookies for [$query]!") + replyTo ! Response(s"Here are the cookies for [$query]!") Behaviors.same } // #request-response-respond diff --git a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/RouterSpec.scala b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/RouterSpec.scala index f0c25f47ab..f2a2a27980 100644 --- a/akka-actor-typed-tests/src/test/scala/docs/akka/typed/RouterSpec.scala +++ b/akka-actor-typed-tests/src/test/scala/docs/akka/typed/RouterSpec.scala @@ -36,8 +36,10 @@ object RouterSpec { } // #pool - + // #group val serviceKey = ServiceKey[Worker.Command]("log-worker") + + // #group } class RouterSpec extends ScalaTestWithActorTestKit("akka.loglevel=warning") with WordSpecLike with LogCapturing { diff --git a/akka-actor/src/main/scala/akka/actor/ActorRef.scala b/akka-actor/src/main/scala/akka/actor/ActorRef.scala index d96a889d92..651134c17a 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRef.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRef.scala @@ -527,7 +527,7 @@ final case class Dropped(message: Any, reason: String, sender: ActorRef, recipie object Dropped { /** - * Convenience for creating `Cropped` without `sender`. + * Convenience for creating `Dropped` without a `sender`. */ def apply(message: Any, reason: String, recipient: ActorRef): Dropped = Dropped(message, reason, ActorRef.noSender, recipient) diff --git a/akka-docs/src/main/paradox/typed/actor-discovery.md b/akka-docs/src/main/paradox/typed/actor-discovery.md index bfe8555afa..f6b9c61d58 100644 --- a/akka-docs/src/main/paradox/typed/actor-discovery.md +++ b/akka-docs/src/main/paradox/typed/actor-discovery.md @@ -96,7 +96,7 @@ the `PingManager` understands. The `Receptionist` also works in a cluster, an actor registered to the receptionist will appear in the receptionist of the other nodes of the cluster. -The state for the receptionist is propagated via @ref:[distributed data](../distributed-data.md) which means that each node +The state for the receptionist is propagated via @ref:[distributed data](distributed-data.md) which means that each node will eventually reach the same set of actors per `ServiceKey`. `Subscription`s and `Find` queries to a clustered receptionist will keep track of cluster reachability and only list diff --git a/akka-docs/src/main/paradox/typed/actor-lifecycle.md b/akka-docs/src/main/paradox/typed/actor-lifecycle.md index e41f47ba41..b9a70bcb1b 100644 --- a/akka-docs/src/main/paradox/typed/actor-lifecycle.md +++ b/akka-docs/src/main/paradox/typed/actor-lifecycle.md @@ -80,7 +80,7 @@ Java : @@snip [IntroSpec.scala](/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/IntroTest.java) { #hello-world } For very simple applications the guardian may contain the actual application logic and handle messages. As soon as the application -handles more than one concern the the guardian should instead just bootstrap the application, spawn the various subsystems as +handles more than one concern the guardian should instead just bootstrap the application, spawn the various subsystems as children and monitor their lifecycles. When the guardian actor stops this will stop the `ActorSystem`. @@ -159,14 +159,14 @@ A way to find running actors is described in @ref:[Actor discovery](actor-discov An actor can stop itself by returning `Behaviors.stopped` as the next behavior. -Child actors can be forced to be stopped after it finishes processing its current message by using the +A child actor can be forced to stop after it finishes processing its current message by using the `stop` method of the `ActorContext` from the parent actor. Only child actors can be stopped in that way. -The child actors will be stopped as part of the shutdown procedure of the parent. +All child actors will be stopped when their parent is stopped. -The `PostStop` signal that results from stopping an actor can be used for cleaning up resources. Note that -a behavior that handles such `PostStop` signal can optionally be defined as a parameter to `Behaviors.stopped` -if different actions is needed when the actor gracefully stops itself from when it is stopped abruptly. +When an actor is stopped, it receives the `PostStop` signal that can be used for cleaning up resources. +A callback function may be specified as parameter to `Behaviors.stopped` to handle the `PostStop` signal +when stopping gracefully. This allows to apply different actions from when it is stopped abruptly. Here is an illustrating example: diff --git a/akka-docs/src/main/paradox/typed/dispatchers.md b/akka-docs/src/main/paradox/typed/dispatchers.md index ea3b70cea0..5d322af4d7 100644 --- a/akka-docs/src/main/paradox/typed/dispatchers.md +++ b/akka-docs/src/main/paradox/typed/dispatchers.md @@ -33,8 +33,8 @@ gives excellent performance in most cases. ## Internal dispatcher -To protect the internal Actors that is spawned by the various Akka modules, a separate internal dispatcher is used by default. -The internal dispatcher can be tuned in a fine grained way with the setting `akka.actor.internal-dispatcher`, it can also +To protect the internal Actors that are spawned by the various Akka modules, a separate internal dispatcher is used by default. +The internal dispatcher can be tuned in a fine-grained way with the setting `akka.actor.internal-dispatcher`, it can also be replaced by another dispatcher by making `akka.actor.internal-dispatcher` an @ref[alias](#dispatcher-aliases). @@ -68,7 +68,7 @@ Java * `DispatcherSelector.blocking` can be used to execute actors that block e.g. a legacy database API that does not support @scala[`Future`]@java[`CompletionStage`]s * `DispatcherSelector.sameAsParent` to use the same dispatcher as the parent actor -The final example shows how to load a custom dispatcher from configuration and relies on this being in your application.conf: +The final example shows how to load a custom dispatcher from configuration and relies on this being in your `application.conf`: @@snip [DispatcherDocSpec.scala](/akka-actor-typed-tests/src/test/scala/docs/akka/typed/DispatchersDocSpec.scala) { #config } @@ -80,21 +80,21 @@ There are 2 different types of message dispatchers: * **Dispatcher** This is an event-based dispatcher that binds a set of Actors to a thread - pool. It is the default dispatcher used if one is not specified. + pool. The default dispatcher is used if no other is specified. - * Sharability: Unlimited + * Shareability: Unlimited * Mailboxes: Any, creates one per Actor * Use cases: Default dispatcher, Bulkheading * Driven by: `java.util.concurrent.ExecutorService`. - Specify using "executor" using "fork-join-executor", "thread-pool-executor" or the FQCN of - an `akka.dispatcher.ExecutorServiceConfigurator`. + Specify using "executor" using "fork-join-executor", "thread-pool-executor" or the fully-qualified + class name of an `akka.dispatcher.ExecutorServiceConfigurator` implementation. * **PinnedDispatcher** This dispatcher dedicates a unique thread for each actor using it; i.e. each actor will have its own thread pool with only one thread in the pool. - * Sharability: None + * Shareability: None * Mailboxes: Any, creates one per Actor * Use cases: Bulkheading * Driven by: Any `akka.dispatch.ThreadPoolExecutorConfigurator`. @@ -271,7 +271,7 @@ unless you @ref:[set up a separate dispatcher for the actor](../dispatchers.md#s One of the most efficient methods of isolating the blocking behavior such that it does not impact the rest of the system is to prepare and use a dedicated dispatcher for all those blocking operations. -This technique is often referred to as as "bulk-heading" or simply "isolating blocking". +This technique is often referred to as "bulk-heading" or simply "isolating blocking". In `application.conf`, the dispatcher dedicated to blocking behavior should be configured as follows: @@ -280,8 +280,8 @@ be configured as follows: @@snip [BlockingDispatcherSample.scala](/akka-docs/src/test/scala/docs/actor/typed/BlockingDispatcherSample.scala) { #my-blocking-dispatcher-config } -A `thread-pool-executor` based dispatcher allows us to set a limit on the number of threads it will host, -and this way we gain tight control over how at-most-how-many blocked threads will be in the system. +A `thread-pool-executor` based dispatcher allows us to limit the number of threads it will host, +and this way we gain tight control over the maximum number of blocked threads the system may use. The exact size should be fine tuned depending on the workload you're expecting to run on this dispatcher. @@ -305,7 +305,7 @@ When blocking operations are run on the `my-blocking-dispatcher`, it uses the threads (up to the configured limit) to handle these operations. The sleeping in this case is nicely isolated to just this dispatcher, and the default one remains unaffected, allowing the rest of the application to proceed as if nothing bad was happening. After -a certain period idleness, threads started by this dispatcher will be shut down. +a certain period of idleness, threads started by this dispatcher will be shut down. In this case, the throughput of other actors was not impacted - they were still served on the default dispatcher. diff --git a/akka-docs/src/main/paradox/typed/interaction-patterns.md b/akka-docs/src/main/paradox/typed/interaction-patterns.md index f36d257f94..b5952f1c13 100644 --- a/akka-docs/src/main/paradox/typed/interaction-patterns.md +++ b/akka-docs/src/main/paradox/typed/interaction-patterns.md @@ -61,7 +61,7 @@ Java ## Request-Response -Many interactions between actors requires one or more response message being sent back from the receiving actor. A response message can be a result of a query, some form of acknowledgment that the message was received and processed or events that the request subscribed to. +Many interactions between actors require one or more response message being sent back from the receiving actor. A response message can be a result of a query, some form of acknowledgment that the message was received and processed or events that the request subscribed to. In Akka the recipient of responses has to be encoded as a field in the message itself, which the recipient can then use to send (tell) a response back. @@ -106,7 +106,7 @@ Java * It is hard to detect that a message request was not delivered or processed (see @ref:[ask](#request-response-with-ask-between-two-actors)) * Unless the protocol already includes a way to provide context, for example a request id that is also sent in the response, it is not possible to tie an interaction to some specific context without introducing a new, - separate, actor (see ask or per session child actor) + separate, actor (see @ref:[ask](#request-response-with-ask-between-two-actors) or @ref:[per session child actor](#per-session-child-actor)) ## Adapted Response @@ -136,9 +136,9 @@ their registration order, i.e. the last registered first. A message adapter (and the returned `ActorRef`) has the same lifecycle as the receiving actor. It's recommended to register the adapters in a top level `Behaviors.setup` or constructor of `AbstractBehavior` but it's possible to -register them later also if needed. +register them later if needed. -The adapter function is running in the receiving actor and can safely access state of it, but if it throws an exception the actor is stopped. +The adapter function is running in the receiving actor and can safely access its state, but if it throws an exception the actor is stopped. **Useful when:** @@ -173,7 +173,7 @@ Java : @@snip [InteractionPatternsTest.java](/akka-actor-typed-tests/src/test/java/jdocs/akka/typed/InteractionPatternsTest.java) { #actor-ask } -The response adapting function is running in the receiving actor and can safely access state of it, but if it throws an exception the actor is stopped. +The response adapting function is running in the receiving actor and can safely access its state, but if it throws an exception the actor is stopped. **Useful when:** @@ -187,12 +187,12 @@ The response adapting function is running in the receiving actor and can safely * There can only be a single response to one `ask` (see @ref:[per session child Actor](#per-session-child-actor)) * When `ask` times out, the receiving actor does not know and may still process it to completion, or even start processing it after the fact - * Finding a good value for the timeout, especially when `ask` is triggers chained `ask`s in the receiving actor. You want a short timeout to be responsive and answer back to the requester, but at the same time you do not want to have many false positives + * Finding a good value for the timeout, especially when `ask` triggers chained `ask`s in the receiving actor. You want a short timeout to be responsive and answer back to the requester, but at the same time you do not want to have many false positives ## Request-Response with ask from outside an Actor -Some times you need to interact with actors from outside of the actor system, this can be done with fire-and-forget as described above or through another version of `ask` that returns a @scala[`Future[Response]`]@java[`CompletionStage`] that is either completed with a successful response or failed with a `TimeoutException` if there was no response within the specified timeout. +Sometimes you need to interact with actors from the outside of the actor system, this can be done with fire-and-forget as described above or through another version of `ask` that returns a @scala[`Future[Response]`]@java[`CompletionStage`] that is either completed with a successful response or failed with a `TimeoutException` if there was no response within the specified timeout. To do this we use @scala[`ActorRef.ask` (or the symbolic `ActorRef.?`) implicitly provided by `akka.actor.typed.scaladsl.AskPattern`]@java[`akka.actor.typed.javadsl.AskPattern.ask`] to send a message to an actor and get a @scala[`Future[Response]`]@java[`CompletionState[Response]`] back. @@ -255,7 +255,7 @@ Therefore it is better to map the result to a message and perform further proces In some cases a complete response to a request can only be created and sent back after collecting multiple answers from other actors. For these kinds of interaction it can be good to delegate the work to a per "session" child actor. The child could also contain arbitrary logic to implement retrying, failing on timeout, tail chopping, progress inspection etc. -Note that this in fact essentially how `ask` is implemented, if all you need is a single response with a timeout it is better to use `ask`. +Note that this is essentially how `ask` is implemented, if all you need is a single response with a timeout it is better to use `ask`. The child is created with the context it needs to do the work, including an `ActorRef` that it can respond to. When the complete result is there the child responds with the result and stops itself. @@ -363,7 +363,7 @@ Java **Problems:** * Increased load since more messages are sent and "work" is performed more than once - * Can't be used when the "work" is not idempotent and must only performed once + * Can't be used when the "work" is not idempotent and must only be performed once * Message protocols with generic types are difficult since the generic types are erased in runtime * Children have life cycles that must be managed to not create a resource leak, it can be easy to miss a scenario where the session actor is not stopped @@ -389,11 +389,11 @@ There are a few things worth noting here: * To get access to the timers you start with `Behaviors.withTimers` that will pass a `TimerScheduler` instance to the function. This can be used with any type of `Behavior`, including `receive`, `receiveMessage`, but also `setup` or any other behavior. -* Each timer has a key and if a new timer with same key is started the previous is cancelled and it's guaranteed that a message from the previous timer is not received, even though it might already be enqueued in the mailbox when the new timer is started. +* Each timer has a key and if a new timer with the same key is started, the previous is cancelled and it's guaranteed that a message from the previous timer is not received, even though it might already be enqueued in the mailbox when the new timer is started. * Both periodic and single message timers are supported. * The `TimerScheduler` is mutable in itself, because it performs and manages the side effects of registering the scheduled tasks. * The `TimerScheduler` is bound to the lifecycle of the actor that owns it and it's cancelled automatically when the actor is stopped. -* `Behaviors.withTimers` can also be used inside `Behaviors.supervise` and it will automatically cancel the started timers correctly when the actor is restarted, so that the new incarnation will not receive scheduled messages from previous incarnation. +* `Behaviors.withTimers` can also be used inside `Behaviors.supervise` and it will automatically cancel the started timers correctly when the actor is restarted, so that the new incarnation will not receive scheduled messages from a previous incarnation. ### Schedule periodically @@ -438,6 +438,9 @@ which may in worst case cause undesired load on the system. `scheduleWithFixedDe ## Responding to a sharded actor +When @ref:[Akka Cluster](cluster.md) is used to @ref:[shard actors](cluster-sharding.md) you need to +take into account that an actor may move or get passivated. + The normal pattern for expecting a reply is to include an @apidoc[akka.actor.typed.ActorRef] in the message, typically a message adapter. This can be used for a sharded actor but if @scala[`ctx.self`]@java[`ctx.getSelf()`] is sent and the sharded actor is moved or passivated then the reply will sent to dead letters. diff --git a/akka-docs/src/main/paradox/typed/routers.md b/akka-docs/src/main/paradox/typed/routers.md index 88491efa6e..03a9ae18d3 100644 --- a/akka-docs/src/main/paradox/typed/routers.md +++ b/akka-docs/src/main/paradox/typed/routers.md @@ -44,7 +44,7 @@ Java The group router is created with a `ServiceKey` and uses the receptionist (see @ref:[Receptionist](actor-discovery.md#receptionist)) to discover available actors for that key and routes messages to one of the currently known registered actors for a key. -Since the receptionist is used this means the group router is cluster aware out of the box. The router route +Since the receptionist is used this means the group router is cluster-aware out of the box. The router sends messages to registered actors on any node in the cluster that is reachable. If no reachable actor exists the router will fallback and route messages to actors on nodes marked as unreachable. @@ -53,7 +53,7 @@ the group router is started the set of routees it knows about is empty, until it it stashes incoming messages and forwards them as soon as it gets a listing from the receptionist. When the router has received a listing from the receptionist and the set of registered actors is empty the router will -drop them (published them to the event stream as `akka.actor.Dropped`). +drop them (publish them to the event stream as `akka.actor.Dropped`). Scala : @@snip [RouterSpec.scala](/akka-actor-typed-tests/src/test/scala/docs/akka/typed/RouterSpec.scala) { #group } @@ -96,4 +96,4 @@ it will not give better performance to create more routees than there are thread Since the router itself is an actor and has a mailbox this means that messages are routed sequentially to the routees where it can be processed in parallel (depending on the available threads in the dispatcher). -In a high throughput use cases the sequential routing could be a bottle neck. Akka Typed does not provide an optimized tool for this. +In a high throughput use cases the sequential routing could become a bottle neck. Akka Typed does not provide an optimized tool for this. diff --git a/akka-docs/src/main/paradox/typed/stash.md b/akka-docs/src/main/paradox/typed/stash.md index 04f2996e76..b34b45d793 100644 --- a/akka-docs/src/main/paradox/typed/stash.md +++ b/akka-docs/src/main/paradox/typed/stash.md @@ -21,9 +21,9 @@ be handled using the actor's current behavior. A typical example when this is useful is if the actor has to load some initial state or initialize some resources before it can accept the first real message. Another example is when the actor -is waiting for something to complete before processing next message. +is waiting for something to complete before processing the next message. -Let's illustrate these two with an example. It's an actor that is used like a single access point +Let's illustrate these two with an example. The `DataAccess` actor below is used like a single access point to a value stored in a database. When it's started it loads current state from the database, and while waiting for that initial value all incoming messages are stashed. diff --git a/project/Paradox.scala b/project/Paradox.scala index bf9120ec35..8c39e4ab4f 100644 --- a/project/Paradox.scala +++ b/project/Paradox.scala @@ -23,9 +23,9 @@ object Paradox { "extref.github.base_url" -> (GitHub.url(version.value) + "/%s"), // for links to our sources "extref.samples.base_url" -> "https://developer.lightbend.com/start/?group=akka&project=%s", "extref.ecs.base_url" -> "https://example.lightbend.com/v1/download/%s", - "scaladoc.akka.base_url" -> "https://doc.akka.io/api/akka/2.5", + "scaladoc.akka.base_url" -> "https://doc.akka.io/api/akka/2.6", "scaladoc.akka.http.base_url" -> "https://doc.akka.io/api/akka-http/current", - "javadoc.akka.base_url" -> "https://doc.akka.io/japi/akka/2.5", + "javadoc.akka.base_url" -> "https://doc.akka.io/japi/akka/2.6", "javadoc.akka.http.base_url" -> "https://doc.akka.io/japi/akka-http/current", "scala.version" -> scalaVersion.value, "scala.binary_version" -> scalaBinaryVersion.value,