Greetings, I have a node with a number of top level actors and cluster 
shards that I want to shut down gracefully. I have added the redacted code 
before for the startup and shutdown via a SystemManagerActor but I am 
staring at it wondering if there is a better way. A number of questions 
occur. 

1. Should I have this SystemManagerActor hold onto the refs of the actors 
it starts and when shutting down send the refs Poison pills, or restart 
them if the system is not shutting down? 
2. If I go with option 1, is there any way that I can make the Cluster 
Shard actors children of the SystemManagerActor? I could easily start the 
other actors as children of the manager. What I am not sure about is the 
cluster singleton and the cluster shards. It seems to me there is no way I 
know to create them as children of other actors.
3. If question 2 is impossible, is it at all appropriate for the actor to 
watch actors that aren't its children? 
4. Any other suggestions? 

Thanks in advance

package actors.system;

public class SystemManagerActor extends UntypedActor {
    private static final Logger.ALogger log = 
Logger.of(SystemManagerActor.class); // play framework logger

    private static ActorSystem system = MyApp.getActorSystem();
    private static Cluster cluster = Cluster.get(system);

    private final CompletableFuture<Void> future;

    // -- Shard regions for cluster sharded actors.
    private final List<ActorRef> shardRegions = Stream.of(
            ShardedActorA.shardRegion(),
            ShardedActorB.shardRegion()
    ).collect(toList());

    // -- Actors that are not sharded.
    private final List<ActorSelection> actors = Stream.of(
            SimpleActorA.actorSelection(),
            SimpleActorB.actorSelection(),
            SingletonActor.actorSelection()
    ).collect(toList());

    public SystemManagerActor(final CompletableFuture<Void> future) {
        this.future = future;
        log.info("Shutting down MyApp ActorSystem actors");
        // wait 5 seconds for load balancer.

        context().system().scheduler().scheduleOnce(Duration.create(5, 
SECONDS), self(),
                SignalMessages.BEGIN_SHUTDOWN, context().dispatcher(), self());
    }

    @Override
    public void onReceive(final Object message) throws Throwable {
        if (message instanceof SignalMessages && 
SignalMessages.BEGIN_SHUTDOWN.equals(message)) {
            shardRegions.forEach(ref -> {
                context().watch(ref);
                ref.tell(ShardRegion.gracefulShutdownInstance(), getSelf());
            });
        } else if (message instanceof Terminated && !shardRegions.isEmpty()) {
            shardRegions.remove(((Terminated) message).getActor());
            if (!shardRegions.isEmpty()) return;
            actors.forEach(actorSelection -> 
actorSelection.tell(PoisonPill.getInstance(), getSelf()));
            log.info("Actors Shut down.");
            cluster.subscribe(getSelf(), ClusterEvent.initialStateAsSnapshot(), 
ClusterEvent.MemberRemoved.class);
            cluster.leave(cluster.selfAddress());
        } else if (message instanceof ClusterEvent.MemberRemoved) {
            // wait 10 seconds for graceful stop.
            context().system().scheduler().scheduleOnce(Duration.create(10, 
SECONDS), self(),
                    SignalMessages.STOP_ACTOR_SYSTEM, context().dispatcher(), 
self());
        } else if (message instanceof SignalMessages && 
SignalMessages.STOP_ACTOR_SYSTEM.equals(message)) {
            system.terminate();
            future.complete(null);
        } else {
            unhandled(message);
        }
    }

    public static CompletableFuture<Void> onStop() {
        final CompletableFuture<Void> future = new CompletableFuture<>();
        MyApp.getActorSystem().actorOf(Props.create(SystemManagerActor.class, 
future));
        return future;
    }

    public static void onStart() {
        system.actorOf(SimpleActorA.props(), SimpleActorA.ACTOR_NAME);
        system.actorOf(SimpleActorB.props(), SimpleActorB.ACTOR_NAME);
        SingletonActor.register();
        ShardedActorA.startShardRegion();
        ShardedActorB.startShardRegion();
    }

    private enum SignalMessages {
        BEGIN_SHUTDOWN, STOP_ACTOR_SYSTEM;
    }
}



-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: 
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to akka-user+unsubscr...@googlegroups.com.
To post to this group, send email to akka-user@googlegroups.com.
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to