simplify the stopping example, #28144 (#29760)

* need for the callback variant should be a rare so we should not
  confuse the users with it in this example
* mention of callback in api docs should be enough
This commit is contained in:
Patrik Nordwall 2020-10-27 17:27:43 +01:00 committed by GitHub
parent 592b1d10ad
commit 8d25ca2012
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 12 additions and 22 deletions

View file

@ -67,9 +67,9 @@ interface GracefulStopDocTest {
private Behavior<Command> onGracefulShutdown() { private Behavior<Command> onGracefulShutdown() {
getContext().getSystem().log().info("Initiating graceful shutdown..."); getContext().getSystem().log().info("Initiating graceful shutdown...");
// perform graceful stop, executing cleanup before final system termination // Here it can perform graceful stop (possibly asynchronous) and when completed
// behavior executing cleanup is passed as a parameter to Actor.stopped // return `Behaviors.stopped()` here or after receiving another message.
return Behaviors.stopped(() -> getContext().getSystem().log().info("Cleanup!")); return Behaviors.stopped();
} }
private Behavior<Command> onPostStop() { private Behavior<Command> onPostStop() {
@ -80,8 +80,6 @@ interface GracefulStopDocTest {
// #master-actor // #master-actor
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// #graceful-shutdown
final ActorSystem<MasterControlProgram.Command> system = final ActorSystem<MasterControlProgram.Command> system =
ActorSystem.create(MasterControlProgram.create(), "B6700"); ActorSystem.create(MasterControlProgram.create(), "B6700");
@ -94,7 +92,6 @@ interface GracefulStopDocTest {
system.tell(MasterControlProgram.GracefulShutdown.INSTANCE); system.tell(MasterControlProgram.GracefulShutdown.INSTANCE);
system.getWhenTerminated().toCompletableFuture().get(3, TimeUnit.SECONDS); system.getWhenTerminated().toCompletableFuture().get(3, TimeUnit.SECONDS);
// #graceful-shutdown
} }
// #worker-actor // #worker-actor

View file

@ -13,7 +13,6 @@ import akka.actor.typed.{ ActorSystem, PostStop }
import akka.actor.testkit.typed.scaladsl.LogCapturing import akka.actor.testkit.typed.scaladsl.LogCapturing
import akka.actor.typed.ActorRef import akka.actor.typed.ActorRef
import org.slf4j.Logger
import scala.concurrent.duration._ import scala.concurrent.duration._
import scala.concurrent.Await import scala.concurrent.Await
import org.scalatest.wordspec.AnyWordSpecLike import org.scalatest.wordspec.AnyWordSpecLike
@ -30,9 +29,6 @@ object GracefulStopDocSpec {
final case class SpawnJob(name: String) extends Command final case class SpawnJob(name: String) extends Command
case object GracefulShutdown extends Command case object GracefulShutdown extends Command
// Predefined cleanup operation
def cleanup(log: Logger): Unit = log.info("Cleaning up!")
def apply(): Behavior[Command] = { def apply(): Behavior[Command] = {
Behaviors Behaviors
.receive[Command] { (context, message) => .receive[Command] { (context, message) =>
@ -43,11 +39,9 @@ object GracefulStopDocSpec {
Behaviors.same Behaviors.same
case GracefulShutdown => case GracefulShutdown =>
context.log.info("Initiating graceful shutdown...") context.log.info("Initiating graceful shutdown...")
// perform graceful stop, executing cleanup before final system termination // Here it can perform graceful stop (possibly asynchronous) and when completed
// behavior executing cleanup is passed as a parameter to Actor.stopped // return `Behaviors.stopped` here or after receiving another message.
Behaviors.stopped { () => Behaviors.stopped
cleanup(context.system.log)
}
} }
} }
.receiveSignal { .receiveSignal {
@ -158,8 +152,6 @@ class GracefulStopDocSpec extends ScalaTestWithActorTestKit with AnyWordSpecLike
} }
"gracefully stop workers and master" in { "gracefully stop workers and master" in {
//#graceful-shutdown
import MasterControlProgram._ import MasterControlProgram._
val system: ActorSystem[Command] = ActorSystem(MasterControlProgram(), "B7700") val system: ActorSystem[Command] = ActorSystem(MasterControlProgram(), "B7700")
@ -175,7 +167,6 @@ class GracefulStopDocSpec extends ScalaTestWithActorTestKit with AnyWordSpecLike
Thread.sleep(100) Thread.sleep(100)
Await.result(system.whenTerminated, 3.seconds) Await.result(system.whenTerminated, 3.seconds)
//#graceful-shutdown
} }
} }
} }

View file

@ -89,6 +89,9 @@ object Behaviors {
* The `PostStop` signal that results from stopping this actor will first be passed to the * The `PostStop` signal that results from stopping this actor will first be passed to the
* current behavior and then the provided `postStop` callback will be invoked. * current behavior and then the provided `postStop` callback will be invoked.
* All other messages and signals will effectively be ignored. * All other messages and signals will effectively be ignored.
*
* An example of when the callback can be useful compared to the `PostStop` signal
* if you want to send a reply to the message that initiated a graceful stop.
*/ */
def stopped[T](postStop: Effect): Behavior[T] = BehaviorImpl.stopped(postStop.apply _) def stopped[T](postStop: Effect): Behavior[T] = BehaviorImpl.stopped(postStop.apply _)

View file

@ -73,6 +73,9 @@ object Behaviors {
* The `PostStop` signal that results from stopping this actor will first be passed to the * The `PostStop` signal that results from stopping this actor will first be passed to the
* current behavior and then the provided `postStop` callback will be invoked. * current behavior and then the provided `postStop` callback will be invoked.
* All other messages and signals will effectively be ignored. * All other messages and signals will effectively be ignored.
*
* An example of when the callback can be useful compared to the `PostStop` signal
* if you want to send a reply to the message that initiated a graceful stop.
*/ */
def stopped[T](postStop: () => Unit): Behavior[T] = BehaviorImpl.stopped(postStop) def stopped[T](postStop: () => Unit): Behavior[T] = BehaviorImpl.stopped(postStop)

View file

@ -165,8 +165,6 @@ A child actor can be forced to stop after it finishes processing its current mes
All child actors will be stopped when their parent is stopped. All child actors will be stopped when their parent is stopped.
When an actor is stopped, it receives the `PostStop` signal that can be used for cleaning up resources. 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 when it is stopped abruptly.
Here is an illustrating example: Here is an illustrating example:
@ -175,7 +173,6 @@ Scala
#imports #imports
#master-actor #master-actor
#worker-actor #worker-actor
#graceful-shutdown
} }
Java Java
@ -183,7 +180,6 @@ Java
#imports #imports
#master-actor #master-actor
#worker-actor #worker-actor
#graceful-shutdown
} }
When cleaning up resources from `PostStop` you should also consider doing the same for the `PreRestart` signal, When cleaning up resources from `PostStop` you should also consider doing the same for the `PreRestart` signal,