package me.hao0.antares.server.cluster.client;
import com.google.common.collect.Lists;
import me.hao0.antares.common.log.Logs;
import me.hao0.antares.common.support.Lifecycle;
import me.hao0.antares.common.support.Component;
import me.hao0.antares.common.util.CollectionUtil;
import me.hao0.antares.common.util.ZkPaths;
import me.hao0.antares.common.zk.ChildListener;
import me.hao0.antares.common.zk.ChildWatcher;
import me.hao0.antares.store.support.AntaresZkClient;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* The app's clients cluster
* Author: haolin
* Email: haolin.h0@gmail.com
*/
public abstract class AppClientCluster extends Component implements Lifecycle {
private final String appName;
private final Set<String> alives = new HashSet<>();
private final AntaresZkClient zk;
private ChildWatcher watcher;
public AppClientCluster(AntaresZkClient zk, String appName){
this.appName = appName;
this.zk = zk;
// get alive clients once
String appClientsPath = ZkPaths.pathOfAppClients(appName);
zk.client().mkdirs(appClientsPath);
List<String> clients = zk.client().gets(appClientsPath);
if (!CollectionUtil.isNullOrEmpty(clients)){
alives.addAll(clients);
}
}
/**
* Get current alive clients of the app
* @return current alive clients of the app
*/
public List<String> alives() {
return Lists.newArrayList(alives);
}
@Override
public void doStart() {
// listen app's clients change
watcher = zk.client().newChildWatcher(ZkPaths.pathOfAppClients(appName), new ChildListener() {
@Override
protected void onAdd(String path, byte[] data) {
// not started, or has shutdown
// prevent multiple redundant notifies before started
if (!started || shutdowned) {
return;
}
String client = ZkPaths.lastNode(path);
if (alives.contains(client)){
return;
}
alives.add(client);
onClientChanged(appName, client, true);
Logs.info("The app({})'s client({}) joined.", appName, client);
}
@Override
protected void onDelete(String path) {
String client = ZkPaths.lastNode(path);
alives.remove(client);
onClientChanged(appName, client, false);
Logs.info("The app({})'s client({}) left.", appName, client);
}
});
}
@Override
public void doShutdown() {
watcher.stop();
}
/**
* Callback when the app's client changed
* @param appName the app name
* @param client the client host
* @param join true is join, false is left
*/
public abstract void onClientChanged(String appName, String client, Boolean join);
}