/* * Copyright (C) 2018-2022 Lightbend Inc. */ package jdocs.cluster; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.time.Duration; import org.apache.pekko.actor.Props; import org.apache.pekko.cluster.metrics.AdaptiveLoadBalancingGroup; import org.apache.pekko.cluster.metrics.AdaptiveLoadBalancingPool; import org.apache.pekko.cluster.metrics.HeapMetricsSelector; import org.apache.pekko.cluster.metrics.SystemLoadAverageMetricsSelector; import org.apache.pekko.cluster.routing.ClusterRouterGroup; import org.apache.pekko.cluster.routing.ClusterRouterGroupSettings; import org.apache.pekko.cluster.routing.ClusterRouterPool; import org.apache.pekko.cluster.routing.ClusterRouterPoolSettings; import org.apache.pekko.actor.ActorRef; import org.apache.pekko.actor.ReceiveTimeout; import org.apache.pekko.actor.AbstractActor; import org.apache.pekko.event.Logging; import org.apache.pekko.event.LoggingAdapter; import org.apache.pekko.routing.FromConfig; // #frontend public class FactorialFrontend extends AbstractActor { final int upToN; final boolean repeat; LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this); ActorRef backend = getContext().actorOf(FromConfig.getInstance().props(), "factorialBackendRouter"); public FactorialFrontend(int upToN, boolean repeat) { this.upToN = upToN; this.repeat = repeat; } @Override public void preStart() { sendJobs(); getContext().setReceiveTimeout(Duration.ofSeconds(10)); } @Override public Receive createReceive() { return receiveBuilder() .match( FactorialResult.class, result -> { if (result.n == upToN) { log.debug("{}! = {}", result.n, result.factorial); if (repeat) sendJobs(); else getContext().stop(getSelf()); } }) .match( ReceiveTimeout.class, x -> { log.info("Timeout"); sendJobs(); }) .build(); } void sendJobs() { log.info("Starting batch of factorials up to [{}]", upToN); for (int n = 1; n <= upToN; n++) { backend.tell(n, getSelf()); } } } // #frontend // not used, only for documentation abstract class FactorialFrontend2 extends AbstractActor { // #router-lookup-in-code int totalInstances = 100; Iterable routeesPaths = Arrays.asList("/user/factorialBackend", ""); boolean allowLocalRoutees = true; Set useRoles = new HashSet<>(Arrays.asList("backend")); ActorRef backend = getContext() .actorOf( new ClusterRouterGroup( new AdaptiveLoadBalancingGroup( HeapMetricsSelector.getInstance(), Collections.emptyList()), new ClusterRouterGroupSettings( totalInstances, routeesPaths, allowLocalRoutees, useRoles)) .props(), "factorialBackendRouter2"); // #router-lookup-in-code } // not used, only for documentation abstract class FactorialFrontend3 extends AbstractActor { // #router-deploy-in-code int totalInstances = 100; int maxInstancesPerNode = 3; boolean allowLocalRoutees = false; Set useRoles = new HashSet<>(Arrays.asList("backend")); ActorRef backend = getContext() .actorOf( new ClusterRouterPool( new AdaptiveLoadBalancingPool( SystemLoadAverageMetricsSelector.getInstance(), 0), new ClusterRouterPoolSettings( totalInstances, maxInstancesPerNode, allowLocalRoutees, useRoles)) .props(Props.create(FactorialBackend.class)), "factorialBackendRouter3"); // #router-deploy-in-code }