add network id

This commit is contained in:
mohammed jasem alaajel 2024-04-22 16:27:14 +04:00
parent 97e6b5c944
commit 91c3845b2e
7 changed files with 78 additions and 39 deletions

View File

@ -45,10 +45,14 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
private final Object SERVERS_TO_PLAYERS_KEY = new Object();
private final LoadingCache<Object, Multimap<String, UUID>> serverToPlayersCache = Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).build(this::serversToPlayersBuilder);
private final UnifiedJedis unifiedJedis;
private final String proxyId;
private final String networkId;
public PlayerDataManager(RedisBungeePlugin<P> plugin) {
this.plugin = plugin;
this.unifiedJedis = plugin.proxyDataManager().unifiedJedis();
this.proxyId = plugin.proxyDataManager().proxyId();
this.networkId = plugin.proxyDataManager().networkId();
}
// handle network wide
@ -84,7 +88,7 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
if (event.getChannel().equals("redisbungee-kick")) {
JSONObject data = new JSONObject(event.getMessage());
String proxy = data.getString("proxy");
if (proxy.equals(plugin.configuration().getProxyId())) {
if (proxy.equals(this.proxyId)) {
return;
}
UUID uuid = UUID.fromString(data.getString("uuid"));
@ -95,7 +99,7 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
if (event.getChannel().equals("redisbungee-serverchange")) {
JSONObject data = new JSONObject(event.getMessage());
String proxy = data.getString("proxy");
if (proxy.equals(plugin.configuration().getProxyId())) {
if (proxy.equals(this.proxyId)) {
return;
}
UUID uuid = UUID.fromString(data.getString("uuid"));
@ -108,7 +112,7 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
if (event.getChannel().equals("redisbungee-player-join")) {
JSONObject data = new JSONObject(event.getMessage());
String proxy = data.getString("proxy");
if (proxy.equals(plugin.configuration().getProxyId())) {
if (proxy.equals(this.proxyId)) {
return;
}
UUID uuid = UUID.fromString(data.getString("uuid"));
@ -118,7 +122,7 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
if (event.getChannel().equals("redisbungee-player-leave")) {
JSONObject data = new JSONObject(event.getMessage());
String proxy = data.getString("proxy");
if (proxy.equals(plugin.configuration().getProxyId())) {
if (proxy.equals(this.proxyId)) {
return;
}
UUID uuid = UUID.fromString(data.getString("uuid"));
@ -129,7 +133,7 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
protected void playerChangedServer(UUID uuid, String from, String to) {
JSONObject data = new JSONObject();
data.put("proxy", plugin.configuration().getProxyId());
data.put("proxy", this.proxyId);
data.put("uuid", uuid);
data.put("from", from);
data.put("to", to);
@ -143,7 +147,7 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
public void kickPlayer(UUID uuid, Component message) {
if (!plugin.handlePlatformKick(uuid, message)) { // handle locally before SENDING a message
JSONObject data = new JSONObject();
data.put("proxy", plugin.configuration().getProxyId());
data.put("proxy", this.proxyId);
data.put("uuid", uuid);
data.put("message", COMPONENT_SERIALIZER.serialize(message));
plugin.proxyDataManager().sendChannelMessage("redisbungee-kick", data.toString());
@ -154,18 +158,18 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
Map<String, String> data = new HashMap<>();
data.put("server", server);
data.put("last-server", server);
unifiedJedis.hset("redis-bungee::player::" + uuid + "::data", data);
unifiedJedis.hset("redis-bungee::" + this.networkId + "::player::" + uuid + "::data", data);
}
protected void addPlayer(final UUID uuid, final InetAddress inetAddress) {
Map<String, String> redisData = new HashMap<>();
redisData.put("last-online", String.valueOf(0));
redisData.put("proxy", plugin.configuration().getProxyId());
redisData.put("proxy", this.proxyId);
redisData.put("ip", inetAddress.getHostAddress());
unifiedJedis.hset("redis-bungee::player::" + uuid + "::data", redisData);
unifiedJedis.hset("redis-bungee::" + this.networkId + "::player::" + uuid + "::data", redisData);
JSONObject data = new JSONObject();
data.put("proxy", plugin.configuration().getProxyId());
data.put("proxy", this.proxyId);
data.put("uuid", uuid);
plugin.proxyDataManager().sendChannelMessage("redisbungee-player-join", data.toString());
plugin.fireEvent(plugin.createPlayerJoinedNetworkEvent(uuid));
@ -173,10 +177,10 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
}
protected void removePlayer(UUID uuid) {
unifiedJedis.hset("redis-bungee::player::" + uuid + "::data", "last-online", String.valueOf(System.currentTimeMillis()));
unifiedJedis.hdel("redis-bungee::player::" + uuid + "::data", "server", "proxy", "ip");
unifiedJedis.hset("redis-bungee::" + this.networkId + "::player::" + uuid + "::data", "last-online", String.valueOf(System.currentTimeMillis()));
unifiedJedis.hdel("redis-bungee::" + this.networkId + "::player::" + uuid + "::data", "server", "proxy", "ip");
JSONObject data = new JSONObject();
data.put("proxy", plugin.configuration().getProxyId());
data.put("proxy", this.proxyId);
data.put("uuid", uuid);
plugin.proxyDataManager().sendChannelMessage("redisbungee-player-leave", data.toString());
plugin.fireEvent(plugin.createPlayerLeftNetworkEvent(uuid));
@ -185,25 +189,25 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
protected String getProxyFromRedis(UUID uuid) {
return unifiedJedis.hget("redis-bungee::player::" + uuid + "::data", "proxy");
return unifiedJedis.hget("redis-bungee::" + this.networkId + "::player::" + uuid + "::data", "proxy");
}
protected String getServerFromRedis(UUID uuid) {
return unifiedJedis.hget("redis-bungee::player::" + uuid + "::data", "server");
return unifiedJedis.hget("redis-bungee::" + this.networkId + "::player::" + uuid + "::data", "server");
}
protected String getLastServerFromRedis(UUID uuid) {
return unifiedJedis.hget("redis-bungee::player::" + uuid + "::data", "last-server");
return unifiedJedis.hget("redis-bungee::" + this.networkId + "::player::" + uuid + "::data", "last-server");
}
protected InetAddress getIpAddressFromRedis(UUID uuid) {
String ip = unifiedJedis.hget("redis-bungee::player::" + uuid + "::data", "ip");
String ip = unifiedJedis.hget("redis-bungee::" + this.networkId + "::player::" + uuid + "::data", "ip");
if (ip == null) return null;
return InetAddresses.forString(ip);
}
protected long getLastOnlineFromRedis(UUID uuid) {
String unixString = unifiedJedis.hget("redis-bungee::player::" + uuid + "::data", "last-online");
String unixString = unifiedJedis.hget("redis-bungee::" + this.networkId + "::player::" + uuid + "::data", "last-online");
if (unixString == null) return -1;
return Long.parseLong(unixString);
}
@ -241,7 +245,7 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
public Multimap<String, UUID> doPooledPipeline(Pipeline pipeline) {
HashMap<UUID, Response<String>> responses = new HashMap<>();
for (UUID uuid : uuids) {
responses.put(uuid, pipeline.hget("redis-bungee::player::" + uuid + "::data", "server"));
responses.put(uuid, pipeline.hget("redis-bungee::" + networkId + "::player::" + uuid + "::data", "server"));
}
pipeline.sync();
responses.forEach((uuid, response) -> builder.put(response.get(), uuid));
@ -252,7 +256,7 @@ public abstract class PlayerDataManager<P, LE, DE, PS extends IPubSubMessageEven
public Multimap<String, UUID> clusterPipeline(ClusterPipeline pipeline) {
HashMap<UUID, Response<String>> responses = new HashMap<>();
for (UUID uuid : uuids) {
responses.put(uuid, pipeline.hget("redis-bungee::player::" + uuid + "::data", "server"));
responses.put(uuid, pipeline.hget("redis-bungee::" + networkId + "::player::" + uuid + "::data", "server"));
}
pipeline.sync();
responses.forEach((uuid, response) -> builder.put(response.get(), uuid));

View File

@ -24,6 +24,7 @@ import com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.gson.Heartbeat
import com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.gson.PubSubPayloadSerializer;
import com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.gson.RunCommandPayloadSerializer;
import com.imaginarycode.minecraft.redisbungee.api.tasks.RedisPipelineTask;
import com.imaginarycode.minecraft.redisbungee.api.util.RedisUtil;
import redis.clients.jedis.*;
import redis.clients.jedis.params.XAddParams;
import redis.clients.jedis.params.XReadParams;
@ -38,7 +39,6 @@ import static com.google.common.base.Preconditions.checkArgument;
public abstract class ProxyDataManager implements Runnable {
private static final String STREAM_ID = "redisbungee-stream";
private static final int MAX_ENTRIES = 10000;
private final AtomicBoolean closed = new AtomicBoolean(false);
@ -49,8 +49,12 @@ public abstract class ProxyDataManager implements Runnable {
// Proxy id, heartbeat (unix epoch from instant), players as int
private final ConcurrentHashMap<String, HeartbeatPayload.HeartbeatData> heartbeats = new ConcurrentHashMap<>();
private final String networkId;
private final String proxyId;
private final String STREAM_ID;
// This different from proxy id, just to detect if there is duplicate proxy using same proxy id
private final UUID dataManagerUUID = UUID.randomUUID();
@ -63,6 +67,8 @@ public abstract class ProxyDataManager implements Runnable {
this.proxyId = this.plugin.configuration().getProxyId();
this.unifiedJedis = plugin.getSummoner().obtainResource();
this.destroyProxyMembers();
this.networkId = plugin.configuration().networkId();
this.STREAM_ID = "network-" + this.networkId + "-redisbungee-stream";
}
public abstract Set<UUID> getLocalOnlineUUIDs();
@ -106,7 +112,7 @@ public abstract class ProxyDataManager implements Runnable {
public Set<UUID> doPooledPipeline(Pipeline pipeline) {
HashSet<Response<Set<String>>> responses = new HashSet<>();
for (String proxyId : proxiesIds()) {
responses.add(pipeline.smembers("redisbungee::proxies::" + proxyId + "::online-players"));
responses.add(pipeline.smembers("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players"));
}
pipeline.sync();
HashSet<UUID> uuids = new HashSet<>();
@ -122,7 +128,7 @@ public abstract class ProxyDataManager implements Runnable {
public Set<UUID> clusterPipeline(ClusterPipeline pipeline) {
HashSet<Response<Set<String>>> responses = new HashSet<>();
for (String proxyId : proxiesIds()) {
responses.add(pipeline.smembers("redisbungee::proxies::" + proxyId + "::online-players"));
responses.add(pipeline.smembers("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players"));
}
pipeline.sync();
HashSet<UUID> uuids = new HashSet<>();
@ -207,8 +213,8 @@ public abstract class ProxyDataManager implements Runnable {
for (UUID uuid : add) {
addString.add(uuid.toString());
}
pipeline.srem("redisbungee::proxies::" + proxyId() + "::online-players", removeString.toArray(new String[]{}));
pipeline.sadd("redisbungee::proxies::" + proxyId() + "::online-players", addString.toArray(new String[]{}));
pipeline.srem("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", removeString.toArray(new String[]{}));
pipeline.sadd("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", addString.toArray(new String[]{}));
pipeline.sync();
return null;
}
@ -223,8 +229,8 @@ public abstract class ProxyDataManager implements Runnable {
for (UUID uuid : add) {
addString.add(uuid.toString());
}
pipeline.srem("redisbungee::proxies::" + proxyId() + "::online-players", removeString.toArray(new String[]{}));
pipeline.sadd("redisbungee::proxies::" + proxyId() + "::online-players", addString.toArray(new String[]{}));
pipeline.srem("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", removeString.toArray(new String[]{}));
pipeline.sadd("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", addString.toArray(new String[]{}));
pipeline.sync();
return null;
}
@ -236,12 +242,12 @@ public abstract class ProxyDataManager implements Runnable {
}
// handle dead proxies "THAT" Didn't send death payload but considered dead due TIMEOUT ~10 seconds
// handle dead proxies "THAT" Didn't send death payload but considered dead due TIMEOUT ~30 seconds
final Set<String> deadProxies = new HashSet<>();
for (Map.Entry<String, HeartbeatPayload.HeartbeatData> stringHeartbeatDataEntry : this.heartbeats.entrySet()) {
String id = stringHeartbeatDataEntry.getKey();
long heartbeat = stringHeartbeatDataEntry.getValue().heartbeat();
if (Instant.now().getEpochSecond() - heartbeat > 10) {
if (Instant.now().getEpochSecond() - heartbeat > RedisUtil.PROXY_TIMEOUT) {
deadProxies.add(id);
cleanProxy(id);
}
@ -251,7 +257,7 @@ public abstract class ProxyDataManager implements Runnable {
@Override
public Void doPooledPipeline(Pipeline pipeline) {
for (String deadProxy : deadProxies) {
pipeline.del("redisbungee::proxies::" + deadProxy + "::online-players");
pipeline.del("redisbungee::" + networkId + "::proxies::" + deadProxy + "::online-players");
}
pipeline.sync();
return null;
@ -260,7 +266,7 @@ public abstract class ProxyDataManager implements Runnable {
@Override
public Void clusterPipeline(ClusterPipeline pipeline) {
for (String deadProxy : deadProxies) {
pipeline.del("redisbungee::proxies::" + deadProxy + "::online-players");
pipeline.del("redisbungee::" + networkId + "::proxies::" + deadProxy + "::online-players");
}
pipeline.sync();
return null;
@ -302,19 +308,19 @@ public abstract class ProxyDataManager implements Runnable {
public void addPlayer(UUID uuid) {
this.unifiedJedis.sadd("redisbungee::proxies::" + this.proxyId + "::online-players", uuid.toString());
this.unifiedJedis.sadd("redisbungee::" + this.networkId + "::proxies::" + this.proxyId + "::online-players", uuid.toString());
}
public void removePlayer(UUID uuid) {
this.unifiedJedis.srem("redisbungee::proxies::" + this.proxyId + "::online-players", uuid.toString());
this.unifiedJedis.srem("redisbungee::" + this.networkId + "::proxies::" + this.proxyId + "::online-players", uuid.toString());
}
private void destroyProxyMembers() {
unifiedJedis.del("redisbungee::proxies::" + this.proxyId + "::online-players");
unifiedJedis.del("redisbungee::" + this.networkId + "::proxies::" + this.proxyId + "::online-players");
}
private Set<UUID> getProxyMembers(String proxyId) {
Set<String> uuidsStrings = unifiedJedis.smembers("redisbungee::proxies::" + proxyId + "::online-players");
Set<String> uuidsStrings = unifiedJedis.smembers("redisbungee::" + this.networkId + "::proxies::" + proxyId + "::online-players");
HashSet<UUID> uuids = new HashSet<>();
for (String proxyMember : uuidsStrings) {
uuids.add(UUID.fromString(proxyMember));
@ -387,4 +393,7 @@ public abstract class ProxyDataManager implements Runnable {
return unifiedJedis;
}
public String networkId() {
return networkId;
}
}

View File

@ -27,9 +27,10 @@ public class RedisBungeeConfiguration {
private final boolean handleMotd;
private final CommandsConfiguration commandsConfiguration;
private final String networkId;
public RedisBungeeConfiguration(String proxyId, List<String> exemptAddresses, boolean kickWhenOnline, boolean handleReconnectToLastServer, boolean handleMotd, CommandsConfiguration commandsConfiguration) {
public RedisBungeeConfiguration(String networkId, String proxyId, List<String> exemptAddresses, boolean kickWhenOnline, boolean handleReconnectToLastServer, boolean handleMotd, CommandsConfiguration commandsConfiguration) {
this.proxyId = proxyId;
ImmutableList.Builder<InetAddress> addressBuilder = ImmutableList.builder();
for (String s : exemptAddresses) {
@ -40,6 +41,7 @@ public class RedisBungeeConfiguration {
this.handleReconnectToLastServer = handleReconnectToLastServer;
this.handleMotd = handleMotd;
this.commandsConfiguration = commandsConfiguration;
this.networkId = networkId;
}
public String getProxyId() {
@ -79,4 +81,8 @@ public class RedisBungeeConfiguration {
public CommandsConfiguration commandsConfiguration() {
return commandsConfiguration;
}
public String networkId() {
return networkId;
}
}

View File

@ -46,6 +46,7 @@ public interface ConfigLoader extends GenericConfigLoader {
final boolean kickWhenOnline = node.getNode("kick-when-online").getBoolean(true);
String redisPassword = node.getNode("redis-password").getString("");
String redisUsername = node.getNode("redis-username").getString("");
String networkId = node.getNode("network-id").getString("main");
String proxyId = node.getNode("proxy-id").getString("proxy-1");
final int maxConnections = node.getNode("max-redis-connections").getInt(10);
@ -70,6 +71,13 @@ public interface ConfigLoader extends GenericConfigLoader {
plugin.logInfo("Overriding current configured proxy id {} and been set to {} by Environment variable REDISBUNGEE_PROXY_ID", proxyId, proxyIdFromEnv);
proxyId = proxyIdFromEnv;
}
String networkIdFromEnv = System.getenv("REDISBUNGEE_NETWORK_ID");
if (networkIdFromEnv != null) {
plugin.logInfo("Overriding current configured network id {} and been set to {} by Environment variable REDISBUNGEE_NETWORK_ID", networkId, networkIdFromEnv);
networkId = networkIdFromEnv;
}
// Configuration sanity checks.
if (proxyId == null || proxyId.isEmpty()) {
String genId = UUID.randomUUID().toString();
@ -81,6 +89,16 @@ public interface ConfigLoader extends GenericConfigLoader {
} else {
plugin.logInfo("Loaded proxy id " + proxyId);
}
if (networkId.isEmpty()) {
networkId = "main";
plugin.logWarn("network id was empty and replaced with 'main'");
}
plugin.logInfo("Loaded network id " + networkId);
boolean reconnectToLastServer = node.getNode("reconnect-to-last-server").getBoolean();
boolean handleMotd = node.getNode("handle-motd").getBoolean(true);
plugin.logInfo("handle reconnect to last server: {}", reconnectToLastServer);
@ -112,7 +130,7 @@ public interface ConfigLoader extends GenericConfigLoader {
boolean installPlist = node.getNode("commands", "redisbungee-legacy", "subcommands", "plist", "install").getBoolean(false);
RedisBungeeConfiguration configuration = new RedisBungeeConfiguration(proxyId, exemptAddresses, kickWhenOnline, reconnectToLastServer, handleMotd, new RedisBungeeConfiguration.CommandsConfiguration(
RedisBungeeConfiguration configuration = new RedisBungeeConfiguration(networkId, proxyId, exemptAddresses, kickWhenOnline, reconnectToLastServer, handleMotd, new RedisBungeeConfiguration.CommandsConfiguration(
redisBungeeEnabled, redisBungeeLegacyEnabled,
new RedisBungeeConfiguration.LegacySubCommandsConfiguration(
findEnabled, glistEnabled, ipEnabled,

View File

@ -8,7 +8,7 @@
# - 'KeyDB' by Snapchat inc https://docs.keydb.dev/docs/download/
# The Redis server you will use.
# The 'Redis', 'ValKey', 'KeyDB' server you will use.
# these settings are ignored when cluster mode is enabled.
redis-server: 127.0.0.1
redis-port: 6379
@ -19,7 +19,7 @@ cluster-mode-enabled: false
# FORMAT:
# redis-cluster-servers:
# - host: 127.0.0.1
# - host: 127.0.0.1`
# port: 2020
# - host: 127.0.0.1
# port: 2021

View File

@ -41,6 +41,7 @@ tasks {
runWaterfall {
waterfallVersion("1.20")
environment["REDISBUNGEE_PROXY_ID"] = "bungeecord-1"
environment["REDISBUNGEE_NETWORK_ID"] = "dev"
}
compileJava {
options.encoding = Charsets.UTF_8.name()

View File

@ -49,6 +49,7 @@ tasks {
runVelocity {
velocityVersion("3.3.0-SNAPSHOT")
environment["REDISBUNGEE_PROXY_ID"] = "velocity-1"
environment["REDISBUNGEE_NETWORK_ID"] = "dev"
}
compileJava {
options.encoding = Charsets.UTF_8.name()