diff --git a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java index d7c2b8ede8..c3e01992e5 100644 --- a/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java +++ b/akka-cluster-typed/src/test/java/jdocs/akka/cluster/typed/SingletonCompileOnlyTest.java @@ -5,82 +5,117 @@ package jdocs.akka.cluster.typed; import akka.actor.typed.*; +import akka.actor.typed.javadsl.AbstractBehavior; +import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.Behaviors; +import akka.actor.typed.javadsl.Receive; -// #import -import akka.cluster.typed.*; import java.time.Duration; + +// #import +import akka.cluster.typed.ClusterSingleton; +import akka.cluster.typed.SingletonActor; + // #import -public class SingletonCompileOnlyTest { +public interface SingletonCompileOnlyTest { // #counter - interface CounterCommand {} + public class Counter extends AbstractBehavior { - public static class Increment implements CounterCommand {} + public interface Command {} - public static class GoodByeCounter implements CounterCommand {} - - public static class GetValue implements CounterCommand { - private final ActorRef replyTo; - - public GetValue(ActorRef replyTo) { - this.replyTo = replyTo; + public enum Increment implements Command { + INSTANCE } - } - public static Behavior counter(String entityId, Integer value) { - return Behaviors.receive(CounterCommand.class) - .onMessage(Increment.class, msg -> counter(entityId, value + 1)) - .onMessage( - GetValue.class, - msg -> { - msg.replyTo.tell(value); - return Behaviors.same(); - }) - .onMessage(GoodByeCounter.class, msg -> Behaviors.stopped()) - .build(); + public static class GetValue implements Command { + private final ActorRef replyTo; + + public GetValue(ActorRef replyTo) { + this.replyTo = replyTo; + } + } + + public enum GoodByeCounter implements Command { + INSTANCE + } + + public static Behavior create() { + return Behaviors.setup(Counter::new); + } + + private final ActorContext context; + private int value = 0; + + private Counter(ActorContext context) { + this.context = context; + } + + @Override + public Receive createReceive() { + return newReceiveBuilder() + .onMessage(Increment.class, msg -> onIncrement()) + .onMessage(GetValue.class, this::onGetValue) + .onMessage(GoodByeCounter.class, msg -> onGoodByCounter()) + .build(); + } + + private Behavior onIncrement() { + value++; + return this; + } + + private Behavior onGetValue(GetValue msg) { + msg.replyTo.tell(value); + return this; + } + + private Behavior onGoodByCounter() { + // Possible async action then stop + return this; + } } // #counter ActorSystem system = ActorSystem.create(Behaviors.empty(), "SingletonExample"); - public void example() { + public static void example() { // #singleton ClusterSingleton singleton = ClusterSingleton.get(system); // Start if needed and provide a proxy to a named singleton - ActorRef proxy = - singleton.init(SingletonActor.of(counter("TheCounter", 0), "GlobalCounter")); + ActorRef proxy = + singleton.init(SingletonActor.of(Counter.create(), "GlobalCounter")); - proxy.tell(new Increment()); + proxy.tell(Counter.Increment.INSTANCE); // #singleton } - public void customStopMessage() { + public static void customStopMessage() { ClusterSingleton singleton = ClusterSingleton.get(system); // #stop-message - SingletonActor counterSingleton = - SingletonActor.of(counter("TheCounter", 0), "GlobalCounter") - .withStopMessage(new GoodByeCounter()); - ActorRef proxy = singleton.init(counterSingleton); + SingletonActor counterSingleton = + SingletonActor.of(Counter.create(), "GlobalCounter") + .withStopMessage(Counter.GoodByeCounter.INSTANCE); + ActorRef proxy = singleton.init(counterSingleton); // #stop-message - proxy.tell(new Increment()); // avoid unused warning + proxy.tell(Counter.Increment.INSTANCE); // avoid unused warning } - public void backoff() { + public static void backoff() { // #backoff ClusterSingleton singleton = ClusterSingleton.get(system); - ActorRef proxy = + ActorRef proxy = singleton.init( SingletonActor.of( - Behaviors.supervise(counter("TheCounter", 0)) + Behaviors.supervise(Counter.create()) .onFailure( SupervisorStrategy.restartWithBackoff( Duration.ofSeconds(1), Duration.ofSeconds(10), 0.2)), "GlobalCounter")); // #backoff - proxy.tell(new Increment()); // avoid unused warning + proxy.tell(Counter.Increment.INSTANCE); // avoid unused warning } } diff --git a/akka-cluster-typed/src/test/scala/docs/akka/cluster/typed/SingletonCompileOnlySpec.scala b/akka-cluster-typed/src/test/scala/docs/akka/cluster/typed/SingletonCompileOnlySpec.scala index 19fd557385..9a5db19390 100644 --- a/akka-cluster-typed/src/test/scala/docs/akka/cluster/typed/SingletonCompileOnlySpec.scala +++ b/akka-cluster-typed/src/test/scala/docs/akka/cluster/typed/SingletonCompileOnlySpec.scala @@ -6,7 +6,6 @@ package docs.akka.cluster.typed import akka.actor.typed.{ ActorRef, ActorSystem, Behavior, SupervisorStrategy } import akka.actor.typed.scaladsl.Behaviors -import akka.cluster.typed.SingletonActor import scala.concurrent.duration._ @@ -15,45 +14,53 @@ object SingletonCompileOnlySpec { val system = ActorSystem(Behaviors.empty, "Singleton") //#counter - trait CounterCommand - case object Increment extends CounterCommand - final case class GetValue(replyTo: ActorRef[Int]) extends CounterCommand - case object GoodByeCounter extends CounterCommand + object Counter { + trait Command + case object Increment extends Command + final case class GetValue(replyTo: ActorRef[Int]) extends Command + case object GoodByeCounter extends Command - def counter(value: Int): Behavior[CounterCommand] = - Behaviors.receiveMessage[CounterCommand] { - case Increment => - counter(value + 1) - case GetValue(replyTo) => - replyTo ! value - Behaviors.same - case GoodByeCounter => - // Do async action then stop - Behaviors.stopped + def apply(): Behavior[Command] = { + def updated(value: Int): Behavior[Command] = { + Behaviors.receiveMessage[Command] { + case Increment => + updated(value + 1) + case GetValue(replyTo) => + replyTo ! value + Behaviors.same + case GoodByeCounter => + // Possible async action then stop + Behaviors.stopped + } + } + + updated(0) } + } //#counter //#singleton import akka.cluster.typed.ClusterSingleton + import akka.cluster.typed.SingletonActor val singletonManager = ClusterSingleton(system) // Start if needed and provide a proxy to a named singleton - val proxy: ActorRef[CounterCommand] = singletonManager.init( - SingletonActor(Behaviors.supervise(counter(0)).onFailure[Exception](SupervisorStrategy.restart), "GlobalCounter")) + val proxy: ActorRef[Counter.Command] = singletonManager.init( + SingletonActor(Behaviors.supervise(Counter()).onFailure[Exception](SupervisorStrategy.restart), "GlobalCounter")) - proxy ! Increment + proxy ! Counter.Increment //#singleton //#stop-message - val singletonActor = SingletonActor(counter(0), "GlobalCounter").withStopMessage(GoodByeCounter) + val singletonActor = SingletonActor(Counter(), "GlobalCounter").withStopMessage(Counter.GoodByeCounter) singletonManager.init(singletonActor) //#stop-message //#backoff - val proxyBackOff: ActorRef[CounterCommand] = singletonManager.init( + val proxyBackOff: ActorRef[Counter.Command] = singletonManager.init( SingletonActor( Behaviors - .supervise(counter(0)) + .supervise(Counter()) .onFailure[Exception](SupervisorStrategy.restartWithBackoff(1.second, 10.seconds, 0.2)), "GlobalCounter")) //#backoff