mirror of
https://github.com/proxiodev/RedisBungee.git
synced 2024-11-23 04:28:01 +00:00
API converted to support RedisCluster
This commit is contained in:
parent
e986d5f1fb
commit
44f9a0945d
@ -6,6 +6,8 @@ import com.google.common.collect.ImmutableSet;
|
|||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.summoners.JedisSummoner;
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.JedisSummoner;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.Summoner;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.util.RedisBungeeMode;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.JedisPool;
|
||||||
@ -311,30 +313,60 @@ public class RedisBungeeAPI {
|
|||||||
* @since 0.7.0
|
* @since 0.7.0
|
||||||
*/
|
*/
|
||||||
public Jedis requestJedis() {
|
public Jedis requestJedis() {
|
||||||
return this.plugin.getJedisSummoner().requestJedis();
|
if (getMode() == RedisBungeeMode.SINGLE) {
|
||||||
|
return ((JedisSummoner) this.plugin.getSummoner()).obtainResource();
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("RedisBungee is on Cluster MODE!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This gets Redis Bungee {@link JedisPool}
|
* This gets Redis Bungee {@link JedisPool}
|
||||||
* @return {@link JedisPool}
|
* @return {@link JedisPool}
|
||||||
* @since 0.6.5
|
* @since 0.6.5
|
||||||
*/
|
*/
|
||||||
public JedisPool getJedisPool() {
|
public JedisPool getJedisPool() {
|
||||||
return this.plugin.getJedisSummoner().getJedisPool();
|
if (getMode() == RedisBungeeMode.SINGLE) {
|
||||||
|
return ((JedisSummoner) this.plugin.getSummoner()).getJedisPool();
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("RedisBungee is on Cluster MODE!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This gets Redis Bungee {@link JedisPool}
|
* returns Summoner class responsible for Single Jedis {@link Jedis}, Cluster Jedis {@link redis.clients.jedis.JedisCluster} handling
|
||||||
* @return {@link JedisPool}
|
|
||||||
* @since 0.6.5
|
|
||||||
*/
|
|
||||||
public JedisSummoner getJedisSummoner() {
|
|
||||||
return this.plugin.getJedisSummoner();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
*
|
||||||
|
* @return {@link Summoner}
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
public Summoner<?> getSummoner() {
|
||||||
|
return this.plugin.getSummoner();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This gives you instance of Jedis Cluster
|
||||||
|
* @return {@link redis.clients.jedis.JedisCluster}
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
public Jedis requestClusterJedis() {
|
||||||
|
if (getMode() == RedisBungeeMode.CLUSTER) {
|
||||||
|
return ((JedisSummoner) this.plugin.getSummoner()).obtainResource();
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("RedisBungee is on single MODE!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shows what mode is RedisBungee is on
|
||||||
|
* @return {@link RedisBungeeMode}
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
public RedisBungeeMode getMode() {
|
||||||
|
return this.plugin.getRedisBungeeMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api instance
|
||||||
* @return the API instance.
|
* @return the API instance.
|
||||||
* @since 0.6.5
|
* @since 0.6.5
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,9 @@ import com.google.common.util.concurrent.UncheckedExecutionException;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.util.RedisTask;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisCluster;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@ -52,12 +54,17 @@ public abstract class AbstractDataManager<P, PL, PD, PS> {
|
|||||||
return plugin.isPlayerOnAServer(player) ? plugin.getPlayerServerName(player) : null;
|
return plugin.isPlayerOnAServer(player) ? plugin.getPlayerServerName(player) : null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return serverCache.get(uuid, new Callable<String>() {
|
return serverCache.get(uuid, new RedisTask<String>(plugin.getApi()) {
|
||||||
@Override
|
@Override
|
||||||
public String call() throws Exception {
|
public String singleJedisTask(Jedis jedis) {
|
||||||
try (Jedis tmpRsc = plugin.getJedisSummoner().requestJedis()) {
|
return Objects.requireNonNull(jedis.hget("player:" + uuid, "server"), "user not found");
|
||||||
return Objects.requireNonNull(tmpRsc.hget("player:" + uuid, "server"), "user not found");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String clusterJedisTask(JedisCluster jedisCluster) {
|
||||||
|
return Objects.requireNonNull(jedisCluster.hget("player:" + uuid, "server"), "user not found");
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (ExecutionException | UncheckedExecutionException e) {
|
} catch (ExecutionException | UncheckedExecutionException e) {
|
||||||
@ -76,12 +83,15 @@ public abstract class AbstractDataManager<P, PL, PD, PS> {
|
|||||||
return plugin.getConfiguration().getServerId();
|
return plugin.getConfiguration().getServerId();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return proxyCache.get(uuid, new Callable<String>() {
|
return proxyCache.get(uuid, new RedisTask<String>(plugin.getApi()) {
|
||||||
@Override
|
@Override
|
||||||
public String call() throws Exception {
|
public String singleJedisTask(Jedis jedis) {
|
||||||
try (Jedis tmpRsc = plugin.getJedisSummoner().requestJedis()) {
|
return Objects.requireNonNull(jedis.hget("player:" + uuid, "proxy"), "user not found");
|
||||||
return Objects.requireNonNull(tmpRsc.hget("player:" + uuid, "proxy"), "user not found");
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public String clusterJedisTask(JedisCluster jedisCluster) {
|
||||||
|
return Objects.requireNonNull(jedisCluster.hget("player:" + uuid, "proxy"), "user not found");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (ExecutionException | UncheckedExecutionException e) {
|
} catch (ExecutionException | UncheckedExecutionException e) {
|
||||||
@ -99,15 +109,21 @@ public abstract class AbstractDataManager<P, PL, PD, PS> {
|
|||||||
return plugin.getPlayerIp(player);
|
return plugin.getPlayerIp(player);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return ipCache.get(uuid, new Callable<InetAddress>() {
|
return ipCache.get(uuid, new RedisTask<InetAddress>(plugin.getApi()) {
|
||||||
@Override
|
@Override
|
||||||
public InetAddress call() throws Exception {
|
public InetAddress singleJedisTask(Jedis jedis) {
|
||||||
try (Jedis tmpRsc = plugin.getJedisSummoner().requestJedis()) {
|
String result = jedis.hget("player:" + uuid, "ip");
|
||||||
String result = tmpRsc.hget("player:" + uuid, "ip");
|
if (result == null)
|
||||||
if (result == null)
|
throw new NullPointerException("user not found");
|
||||||
throw new NullPointerException("user not found");
|
return InetAddresses.forString(result);
|
||||||
return InetAddresses.forString(result);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public InetAddress clusterJedisTask(JedisCluster jedisCluster) {
|
||||||
|
String result = jedisCluster.hget("player:" + uuid, "ip");
|
||||||
|
if (result == null)
|
||||||
|
throw new NullPointerException("user not found");
|
||||||
|
return InetAddresses.forString(result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (ExecutionException | UncheckedExecutionException e) {
|
} catch (ExecutionException | UncheckedExecutionException e) {
|
||||||
@ -125,13 +141,17 @@ public abstract class AbstractDataManager<P, PL, PD, PS> {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return lastOnlineCache.get(uuid, new Callable<Long>() {
|
return lastOnlineCache.get(uuid, new RedisTask<Long>(plugin.getApi()) {
|
||||||
@Override
|
@Override
|
||||||
public Long call() throws Exception {
|
public Long singleJedisTask(Jedis jedis) {
|
||||||
try (Jedis tmpRsc = plugin.getJedisSummoner().requestJedis()) {
|
String result = jedis.hget("player:" + uuid, "online");
|
||||||
String result = tmpRsc.hget("player:" + uuid, "online");
|
return result == null ? -1 : Long.parseLong(result);
|
||||||
return result == null ? -1 : Long.valueOf(result);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public Long clusterJedisTask(JedisCluster jedisCluster) {
|
||||||
|
String result = jedisCluster.hget("player:" + uuid, "online");
|
||||||
|
return result == null ? -1 : Long.parseLong(result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
@ -149,6 +169,7 @@ public abstract class AbstractDataManager<P, PL, PD, PS> {
|
|||||||
|
|
||||||
// Invalidate all entries related to this player, since they now lie. (call invalidate(uuid))
|
// Invalidate all entries related to this player, since they now lie. (call invalidate(uuid))
|
||||||
public abstract void onPostLogin(PL event);
|
public abstract void onPostLogin(PL event);
|
||||||
|
|
||||||
// Invalidate all entries related to this player, since they now lie. (call invalidate(uuid))
|
// Invalidate all entries related to this player, since they now lie. (call invalidate(uuid))
|
||||||
public abstract void onPlayerDisconnect(PD event);
|
public abstract void onPlayerDisconnect(PD event);
|
||||||
|
|
||||||
@ -181,7 +202,8 @@ public abstract class AbstractDataManager<P, PL, PD, PS> {
|
|||||||
Object event;
|
Object event;
|
||||||
try {
|
try {
|
||||||
event = plugin.getNetworkJoinEventClass().getDeclaredConstructor(UUID.class).newInstance(message1.getTarget());
|
event = plugin.getNetworkJoinEventClass().getDeclaredConstructor(UUID.class).newInstance(message1.getTarget());
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
||||||
|
NoSuchMethodException e) {
|
||||||
throw new RuntimeException("unable to dispatch an network join event", e);
|
throw new RuntimeException("unable to dispatch an network join event", e);
|
||||||
}
|
}
|
||||||
plugin.callEvent(event);
|
plugin.callEvent(event);
|
||||||
@ -200,7 +222,8 @@ public abstract class AbstractDataManager<P, PL, PD, PS> {
|
|||||||
Object event;
|
Object event;
|
||||||
try {
|
try {
|
||||||
event = plugin.getNetworkQuitEventClass().getDeclaredConstructor(UUID.class).newInstance(message2.getTarget());
|
event = plugin.getNetworkQuitEventClass().getDeclaredConstructor(UUID.class).newInstance(message2.getTarget());
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
||||||
|
NoSuchMethodException e) {
|
||||||
throw new RuntimeException("unable to dispatch an network quit event", e);
|
throw new RuntimeException("unable to dispatch an network quit event", e);
|
||||||
}
|
}
|
||||||
plugin.callEvent(event);
|
plugin.callEvent(event);
|
||||||
@ -217,7 +240,8 @@ public abstract class AbstractDataManager<P, PL, PD, PS> {
|
|||||||
Object event;
|
Object event;
|
||||||
try {
|
try {
|
||||||
event = plugin.getServerChangeEventClass().getDeclaredConstructor(UUID.class, String.class, String.class).newInstance(message3.getTarget(), ((ServerChangePayload) message3.getPayload()).getOldServer(), ((ServerChangePayload) message3.getPayload()).getServer());
|
event = plugin.getServerChangeEventClass().getDeclaredConstructor(UUID.class, String.class, String.class).newInstance(message3.getTarget(), ((ServerChangePayload) message3.getPayload()).getOldServer(), ((ServerChangePayload) message3.getPayload()).getServer());
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
||||||
|
NoSuchMethodException e) {
|
||||||
throw new RuntimeException("unable to dispatch an server change event", e);
|
throw new RuntimeException("unable to dispatch an server change event", e);
|
||||||
}
|
}
|
||||||
plugin.callEvent(event);
|
plugin.callEvent(event);
|
||||||
@ -275,7 +299,7 @@ public abstract class AbstractDataManager<P, PL, PD, PS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ServerChangePayload{
|
public static class ServerChangePayload {
|
||||||
private final String server;
|
private final String server;
|
||||||
private final String oldServer;
|
private final String oldServer;
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.internal;
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.util.RedisTask;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisCluster;
|
||||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
public class PubSubListener implements Runnable {
|
public class PubSubListener implements Runnable {
|
||||||
private JedisPubSubHandler jpsh;
|
private JedisPubSubHandler jpsh;
|
||||||
@ -21,27 +22,58 @@ public class PubSubListener implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try (Jedis rsc = plugin.getJedisSummoner().requestJedis()) {
|
RedisTask<Void> subTask = new RedisTask<Void>(plugin.getApi()) {
|
||||||
try {
|
@Override
|
||||||
|
public Void singleJedisTask(Jedis jedis) {
|
||||||
jpsh = new JedisPubSubHandler(plugin);
|
|
||||||
addedChannels.add("redisbungee-" + plugin.getConfiguration().getServerId());
|
|
||||||
addedChannels.add("redisbungee-allservers");
|
|
||||||
addedChannels.add("redisbungee-data");
|
|
||||||
rsc.subscribe(jpsh, addedChannels.toArray(new String[0]));
|
|
||||||
} catch (Exception e) {
|
|
||||||
// FIXME: Extremely ugly hack
|
|
||||||
// Attempt to unsubscribe this instance and try again.
|
|
||||||
plugin.logWarn("PubSub error, attempting to recover.");
|
|
||||||
try {
|
try {
|
||||||
jpsh.unsubscribe();
|
jpsh = new JedisPubSubHandler(plugin);
|
||||||
} catch (Exception e1) {
|
addedChannels.add("redisbungee-" + plugin.getConfiguration().getServerId());
|
||||||
|
addedChannels.add("redisbungee-allservers");
|
||||||
|
addedChannels.add("redisbungee-data");
|
||||||
|
jedis.subscribe(jpsh, addedChannels.toArray(new String[0]));
|
||||||
|
} catch (Exception e) {
|
||||||
|
// FIXME: Extremely ugly hack
|
||||||
|
// Attempt to unsubscribe this instance and try again.
|
||||||
|
plugin.logWarn("PubSub error, attempting to recover.");
|
||||||
|
try {
|
||||||
|
jpsh.unsubscribe();
|
||||||
|
} catch (Exception e1) {
|
||||||
/* This may fail with
|
/* This may fail with
|
||||||
- java.net.SocketException: Broken pipe
|
- java.net.SocketException: Broken pipe
|
||||||
- redis.clients.jedis.exceptions.JedisConnectionException: JedisPubSub was not subscribed to a Jedis instance
|
- redis.clients.jedis.exceptions.JedisConnectionException: JedisPubSub was not subscribed to a Jedis instance
|
||||||
*/
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void clusterJedisTask(JedisCluster jedisCluster) {
|
||||||
|
try {
|
||||||
|
jpsh = new JedisPubSubHandler(plugin);
|
||||||
|
addedChannels.add("redisbungee-" + plugin.getConfiguration().getServerId());
|
||||||
|
addedChannels.add("redisbungee-allservers");
|
||||||
|
addedChannels.add("redisbungee-data");
|
||||||
|
jedisCluster.subscribe(jpsh, addedChannels.toArray(new String[0]));
|
||||||
|
} catch (Exception e) {
|
||||||
|
// FIXME: Extremely ugly hack
|
||||||
|
// Attempt to unsubscribe this instance and try again.
|
||||||
|
plugin.logWarn("PubSub error, attempting to recover.");
|
||||||
|
try {
|
||||||
|
jpsh.unsubscribe();
|
||||||
|
} catch (Exception e1) {
|
||||||
|
/* This may fail with
|
||||||
|
- java.net.SocketException: Broken pipe
|
||||||
|
- redis.clients.jedis.exceptions.JedisConnectionException: JedisPubSub was not subscribed to a Jedis instance
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
subTask.execute();
|
||||||
} catch (JedisConnectionException e) {
|
} catch (JedisConnectionException e) {
|
||||||
plugin.logWarn("PubSub error, attempting to recover in 5 secs.");
|
plugin.logWarn("PubSub error, attempting to recover in 5 secs.");
|
||||||
plugin.executeAsyncAfter(this, TimeUnit.SECONDS, 5);
|
plugin.executeAsyncAfter(this, TimeUnit.SECONDS, 5);
|
||||||
|
@ -2,7 +2,8 @@ package com.imaginarycode.minecraft.redisbungee.internal;
|
|||||||
|
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.summoners.JedisSummoner;
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.Summoner;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.util.RedisBungeeMode;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.util.uuid.UUIDTranslator;
|
import com.imaginarycode.minecraft.redisbungee.internal.util.uuid.UUIDTranslator;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
|
|
||||||
@ -31,11 +32,7 @@ public interface RedisBungeePlugin<P> extends EventsPlatform{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Jedis requestJedis();
|
Summoner<?> getSummoner();
|
||||||
|
|
||||||
boolean isJedisAvailable();
|
|
||||||
|
|
||||||
JedisSummoner getJedisSummoner();
|
|
||||||
|
|
||||||
RedisBungeeConfiguration getConfiguration();
|
RedisBungeeConfiguration getConfiguration();
|
||||||
|
|
||||||
@ -101,4 +98,6 @@ public interface RedisBungeePlugin<P> extends EventsPlatform{
|
|||||||
|
|
||||||
void loadConfig() throws Exception;
|
void loadConfig() throws Exception;
|
||||||
|
|
||||||
|
RedisBungeeMode getRedisBungeeMode();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal.summoners;
|
||||||
|
|
||||||
|
import redis.clients.jedis.JedisCluster;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ClusterJedisSummoner implements Summoner<JedisCluster> {
|
||||||
|
public final JedisCluster jedisCluster;
|
||||||
|
private boolean closed = false;
|
||||||
|
|
||||||
|
public ClusterJedisSummoner(JedisCluster jedisCluster) {
|
||||||
|
this.jedisCluster = jedisCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JedisCluster obtainResource() {
|
||||||
|
return jedisCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return !closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
this.closed = true;
|
||||||
|
jedisCluster.close();
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,35 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.internal.summoners;
|
package com.imaginarycode.minecraft.redisbungee.internal.summoners;
|
||||||
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisCluster;
|
|
||||||
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class JedisSummoner implements Summoner<Jedis> {
|
||||||
|
|
||||||
/**
|
private final JedisPool jedisPool;
|
||||||
* This class intended for future release to support redis sentinel or redis clusters
|
|
||||||
*
|
|
||||||
* @author Ham1255
|
|
||||||
* @since 0.7.0
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface JedisSummoner extends Closeable {
|
|
||||||
|
|
||||||
Jedis requestJedis();
|
public JedisSummoner(JedisPool jedisPool) {
|
||||||
|
this.jedisPool = jedisPool;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isJedisAvailable();
|
@Override
|
||||||
|
public Jedis obtainResource() {
|
||||||
|
return jedisPool.getResource();
|
||||||
|
}
|
||||||
|
|
||||||
JedisPool getJedisPool();
|
public JedisPool getJedisPool() {
|
||||||
|
return this.jedisPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return !jedisPool.isClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
this.jedisPool.close();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.internal.summoners;
|
|
||||||
|
|
||||||
import redis.clients.jedis.Jedis;
|
|
||||||
import redis.clients.jedis.JedisPool;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class SinglePoolJedisSummoner implements JedisSummoner {
|
|
||||||
final JedisPool jedisPool;
|
|
||||||
|
|
||||||
public SinglePoolJedisSummoner(JedisPool jedisPool) {
|
|
||||||
this.jedisPool = jedisPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Jedis requestJedis() {
|
|
||||||
return this.jedisPool.getResource();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isJedisAvailable() {
|
|
||||||
return !this.jedisPool.isClosed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JedisPool getJedisPool() {
|
|
||||||
return this.jedisPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
jedisPool.close();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal.summoners;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class intended for future release to support redis sentinel or redis clusters
|
||||||
|
*
|
||||||
|
* @author Ham1255
|
||||||
|
* @since 0.7.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface Summoner<P> extends Closeable {
|
||||||
|
|
||||||
|
P obtainResource();
|
||||||
|
|
||||||
|
boolean isAvailable();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -2,6 +2,7 @@ package com.imaginarycode.minecraft.redisbungee.internal.util;
|
|||||||
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisCluster;
|
||||||
import redis.clients.jedis.exceptions.JedisDataException;
|
import redis.clients.jedis.exceptions.JedisDataException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -14,10 +15,20 @@ public class LuaManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Script createScript(String script) {
|
public Script createScript(String script) {
|
||||||
try (Jedis jedis = plugin.getJedisSummoner().requestJedis()) {
|
RedisTask<Script> scriptRedisTask = new RedisTask<Script>(plugin.getApi()) {
|
||||||
String hash = jedis.scriptLoad(script);
|
@Override
|
||||||
return new Script(script, hash);
|
public Script singleJedisTask(Jedis jedis) {
|
||||||
}
|
String hash = jedis.scriptLoad(script);
|
||||||
|
return new Script(script, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Script clusterJedisTask(JedisCluster jedisCluster) {
|
||||||
|
String hash = jedisCluster.scriptLoad(script, null);
|
||||||
|
return new Script(script, hash);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return scriptRedisTask.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Script {
|
public class Script {
|
||||||
@ -38,21 +49,40 @@ public class LuaManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Object eval(List<String> keys, List<String> args) {
|
public Object eval(List<String> keys, List<String> args) {
|
||||||
Object data;
|
RedisTask<Object> objectRedisTask = new RedisTask<Object>(plugin.getApi()) {
|
||||||
|
@Override
|
||||||
try (Jedis jedis = plugin.getJedisSummoner().requestJedis()) {
|
public Object singleJedisTask(Jedis jedis) {
|
||||||
try {
|
Object data;
|
||||||
data = jedis.evalsha(hashed, keys, args);
|
try {
|
||||||
} catch (JedisDataException e) {
|
data = jedis.evalsha(hashed, keys, args);
|
||||||
if (e.getMessage().startsWith("NOSCRIPT")) {
|
} catch (JedisDataException e) {
|
||||||
data = jedis.eval(script, keys, args);
|
if (e.getMessage().startsWith("NOSCRIPT")) {
|
||||||
} else {
|
data = jedis.eval(script, keys, args);
|
||||||
throw e;
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
@Override
|
||||||
|
public Object clusterJedisTask(JedisCluster jedisCluster) {
|
||||||
|
Object data;
|
||||||
|
try {
|
||||||
|
data = jedisCluster.evalsha(hashed, keys, args);
|
||||||
|
} catch (JedisDataException e) {
|
||||||
|
if (e.getMessage().startsWith("NOSCRIPT")) {
|
||||||
|
data = jedisCluster.eval(script, keys, args);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return objectRedisTask.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal.util;
|
||||||
|
|
||||||
|
public enum RedisBungeeMode {
|
||||||
|
SINGLE, CLUSTER
|
||||||
|
}
|
@ -1,48 +0,0 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.internal.util;
|
|
||||||
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
|
||||||
import redis.clients.jedis.Jedis;
|
|
||||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class RedisCallable<T> implements Callable<T>, Runnable {
|
|
||||||
private final RedisBungeePlugin<?> plugin;
|
|
||||||
|
|
||||||
public RedisCallable(RedisBungeePlugin<?> plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T call() {
|
|
||||||
return run(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
call();
|
|
||||||
}
|
|
||||||
|
|
||||||
private T run(boolean retry) {
|
|
||||||
try (Jedis jedis = plugin.getJedisSummoner().requestJedis()) {
|
|
||||||
return call(jedis);
|
|
||||||
} catch (JedisConnectionException e) {
|
|
||||||
plugin.logFatal("Unable to get connection");
|
|
||||||
|
|
||||||
if (!retry) {
|
|
||||||
// Wait one second before retrying the task
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e1) {
|
|
||||||
throw new RuntimeException("task failed to run", e1);
|
|
||||||
}
|
|
||||||
return run(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RuntimeException("task failed to run");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract T call(Jedis jedis);
|
|
||||||
}
|
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal.util;
|
||||||
|
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.ClusterJedisSummoner;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.JedisSummoner;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.Summoner;
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisCluster;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public abstract class RedisTask<V> implements Runnable, Callable<V> {
|
||||||
|
|
||||||
|
private final Summoner<?> summoner;
|
||||||
|
private final RedisBungeeAPI api;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V call() throws Exception {
|
||||||
|
return execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedisTask(RedisBungeeAPI api) {
|
||||||
|
this.api = api;
|
||||||
|
this.summoner = api.getSummoner();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract V singleJedisTask(Jedis jedis);
|
||||||
|
|
||||||
|
public abstract V clusterJedisTask(JedisCluster jedisCluster);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
this.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public V execute(){
|
||||||
|
if (api.getMode() == RedisBungeeMode.SINGLE) {
|
||||||
|
JedisSummoner jedisSummoner = (JedisSummoner) summoner;
|
||||||
|
try (Jedis jedis = jedisSummoner.obtainResource()) {
|
||||||
|
return this.singleJedisTask(jedis);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (api.getMode() == RedisBungeeMode.CLUSTER) {
|
||||||
|
ClusterJedisSummoner clusterJedisSummoner = (ClusterJedisSummoner) summoner;
|
||||||
|
return this.clusterJedisTask(clusterJedisSummoner.obtainResource());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,16 +4,18 @@ import com.google.common.base.Charsets;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
|
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.util.RedisTask;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisCluster;
|
||||||
import redis.clients.jedis.Pipeline;
|
import redis.clients.jedis.Pipeline;
|
||||||
import redis.clients.jedis.exceptions.JedisException;
|
import redis.clients.jedis.exceptions.JedisException;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public final class UUIDTranslator {
|
public final class UUIDTranslator {
|
||||||
@ -41,7 +43,7 @@ public final class UUIDTranslator {
|
|||||||
uuidToNameMap.put(uuid, entry);
|
uuidToNameMap.put(uuid, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final UUID getTranslatedUuid(@NonNull String player, boolean expensiveLookups) {
|
public UUID getTranslatedUuid(@NonNull String player, boolean expensiveLookups) {
|
||||||
// If the player is online, give them their UUID.
|
// If the player is online, give them their UUID.
|
||||||
// Remember, local data > remote data.
|
// Remember, local data > remote data.
|
||||||
if (plugin.getPlayer(player) != null)
|
if (plugin.getPlayer(player) != null)
|
||||||
@ -71,43 +73,88 @@ public final class UUIDTranslator {
|
|||||||
if (!plugin.isOnlineMode()) {
|
if (!plugin.isOnlineMode()) {
|
||||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player).getBytes(Charsets.UTF_8));
|
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player).getBytes(Charsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
RedisTask<UUID> redisTask = new RedisTask<UUID>(plugin.getApi()) {
|
||||||
|
@Override
|
||||||
|
public UUID singleJedisTask(Jedis jedis) {
|
||||||
|
String stored = jedis.hget("uuid-cache", player.toLowerCase());
|
||||||
|
if (stored != null) {
|
||||||
|
// Found an entry value. Deserialize it.
|
||||||
|
CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
|
||||||
|
|
||||||
|
// Check for expiry:
|
||||||
|
if (entry.expired()) {
|
||||||
|
jedis.hdel("uuid-cache", player.toLowerCase());
|
||||||
|
// Doesn't hurt to also remove the UUID entry as well.
|
||||||
|
jedis.hdel("uuid-cache", entry.getUuid().toString());
|
||||||
|
} else {
|
||||||
|
nameToUuidMap.put(player.toLowerCase(), entry);
|
||||||
|
uuidToNameMap.put(entry.getUuid(), entry);
|
||||||
|
return entry.getUuid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// That didn't work. Let's ask Mojang.
|
||||||
|
if (!expensiveLookups || !plugin.isOnlineMode())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Map<String, UUID> uuidMap1;
|
||||||
|
try {
|
||||||
|
uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call();
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.logFatal("Unable to fetch UUID from Mojang for " + player);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, UUID> entry : uuidMap1.entrySet()) {
|
||||||
|
if (entry.getKey().equalsIgnoreCase(player)) {
|
||||||
|
persistInfo(entry.getKey(), entry.getValue(), jedis);
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID clusterJedisTask(JedisCluster jedisCluster) {
|
||||||
|
String stored = jedisCluster.hget("uuid-cache", player.toLowerCase());
|
||||||
|
if (stored != null) {
|
||||||
|
// Found an entry value. Deserialize it.
|
||||||
|
CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
|
||||||
|
|
||||||
|
// Check for expiry:
|
||||||
|
if (entry.expired()) {
|
||||||
|
jedisCluster.hdel("uuid-cache", player.toLowerCase());
|
||||||
|
// Doesn't hurt to also remove the UUID entry as well.
|
||||||
|
jedisCluster.hdel("uuid-cache", entry.getUuid().toString());
|
||||||
|
} else {
|
||||||
|
nameToUuidMap.put(player.toLowerCase(), entry);
|
||||||
|
uuidToNameMap.put(entry.getUuid(), entry);
|
||||||
|
return entry.getUuid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// That didn't work. Let's ask Mojang.
|
||||||
|
if (!expensiveLookups || !plugin.isOnlineMode())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Map<String, UUID> uuidMap1;
|
||||||
|
try {
|
||||||
|
uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call();
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.logFatal("Unable to fetch UUID from Mojang for " + player);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, UUID> entry : uuidMap1.entrySet()) {
|
||||||
|
if (entry.getKey().equalsIgnoreCase(player)) {
|
||||||
|
persistInfo(entry.getKey(), entry.getValue(), jedisCluster);
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
// Let's try Redis.
|
// Let's try Redis.
|
||||||
try (Jedis jedis = plugin.getJedisSummoner().requestJedis()) {
|
try {
|
||||||
String stored = jedis.hget("uuid-cache", player.toLowerCase());
|
return redisTask.execute();
|
||||||
if (stored != null) {
|
|
||||||
// Found an entry value. Deserialize it.
|
|
||||||
CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
|
|
||||||
|
|
||||||
// Check for expiry:
|
|
||||||
if (entry.expired()) {
|
|
||||||
jedis.hdel("uuid-cache", player.toLowerCase());
|
|
||||||
// Doesn't hurt to also remove the UUID entry as well.
|
|
||||||
jedis.hdel("uuid-cache", entry.getUuid().toString());
|
|
||||||
} else {
|
|
||||||
nameToUuidMap.put(player.toLowerCase(), entry);
|
|
||||||
uuidToNameMap.put(entry.getUuid(), entry);
|
|
||||||
return entry.getUuid();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// That didn't work. Let's ask Mojang.
|
|
||||||
if (!expensiveLookups || !plugin.isOnlineMode())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Map<String, UUID> uuidMap1;
|
|
||||||
try {
|
|
||||||
uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call();
|
|
||||||
} catch (Exception e) {
|
|
||||||
plugin.logFatal("Unable to fetch UUID from Mojang for " + player);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (Map.Entry<String, UUID> entry : uuidMap1.entrySet()) {
|
|
||||||
if (entry.getKey().equalsIgnoreCase(player)) {
|
|
||||||
persistInfo(entry.getKey(), entry.getValue(), jedis);
|
|
||||||
return entry.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JedisException e) {
|
} catch (JedisException e) {
|
||||||
plugin.logFatal("Unable to fetch UUID for " + player);
|
plugin.logFatal("Unable to fetch UUID for " + player);
|
||||||
}
|
}
|
||||||
@ -115,7 +162,7 @@ public final class UUIDTranslator {
|
|||||||
return null; // Nope, game over!
|
return null; // Nope, game over!
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getNameFromUuid(@NonNull UUID player, boolean expensiveLookups) {
|
public String getNameFromUuid(@NonNull UUID player, boolean expensiveLookups) {
|
||||||
// If the player is online, give them their UUID.
|
// If the player is online, give them their UUID.
|
||||||
// Remember, local data > remote data.
|
// Remember, local data > remote data.
|
||||||
if (plugin.getPlayer(player) != null)
|
if (plugin.getPlayer(player) != null)
|
||||||
@ -130,61 +177,108 @@ public final class UUIDTranslator {
|
|||||||
uuidToNameMap.remove(player);
|
uuidToNameMap.remove(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Okay, it wasn't locally cached. Let's try Redis.
|
RedisTask<String> redisTask = new RedisTask<String>(plugin.getApi()) {
|
||||||
try (Jedis jedis = plugin.getJedisSummoner().requestJedis()) {
|
@Override
|
||||||
String stored = jedis.hget("uuid-cache", player.toString());
|
public String singleJedisTask(Jedis jedis) {
|
||||||
if (stored != null) {
|
String stored = jedis.hget("uuid-cache", player.toString());
|
||||||
// Found an entry value. Deserialize it.
|
if (stored != null) {
|
||||||
CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
|
// Found an entry value. Deserialize it.
|
||||||
|
CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
|
||||||
|
|
||||||
// Check for expiry:
|
// Check for expiry:
|
||||||
if (entry.expired()) {
|
if (entry.expired()) {
|
||||||
jedis.hdel("uuid-cache", player.toString());
|
jedis.hdel("uuid-cache", player.toString());
|
||||||
// Doesn't hurt to also remove the named entry as well.
|
// Doesn't hurt to also remove the named entry as well.
|
||||||
// TODO: Since UUIDs are fixed, we could look up the name and see if the UUID matches.
|
// TODO: Since UUIDs are fixed, we could look up the name and see if the UUID matches.
|
||||||
jedis.hdel("uuid-cache", entry.getName());
|
jedis.hdel("uuid-cache", entry.getName());
|
||||||
} else {
|
} else {
|
||||||
nameToUuidMap.put(entry.getName().toLowerCase(), entry);
|
nameToUuidMap.put(entry.getName().toLowerCase(), entry);
|
||||||
uuidToNameMap.put(player, entry);
|
uuidToNameMap.put(player, entry);
|
||||||
return entry.getName();
|
return entry.getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!expensiveLookups || !plugin.isOnlineMode())
|
if (!expensiveLookups || !plugin.isOnlineMode())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// That didn't work. Let's ask Mojang. This call may fail, because Mojang is insane.
|
// That didn't work. Let's ask Mojang. This call may fail, because Mojang is insane.
|
||||||
String name;
|
String name;
|
||||||
try {
|
try {
|
||||||
List<String> nameHist = NameFetcher.nameHistoryFromUuid(player);
|
List<String> nameHist = NameFetcher.nameHistoryFromUuid(player);
|
||||||
name = Iterables.getLast(nameHist, null);
|
name = Iterables.getLast(nameHist, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
plugin.logFatal("Unable to fetch name from Mojang for " + player);
|
plugin.logFatal("Unable to fetch name from Mojang for " + player);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (name != null) {
|
||||||
|
persistInfo(name, player, jedis);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != null) {
|
@Override
|
||||||
persistInfo(name, player, jedis);
|
public String clusterJedisTask(JedisCluster jedisCluster) {
|
||||||
return name;
|
String stored = jedisCluster.hget("uuid-cache", player.toString());
|
||||||
}
|
if (stored != null) {
|
||||||
|
// Found an entry value. Deserialize it.
|
||||||
|
CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
|
||||||
|
|
||||||
return null;
|
// Check for expiry:
|
||||||
|
if (entry.expired()) {
|
||||||
|
jedisCluster.hdel("uuid-cache", player.toString());
|
||||||
|
// Doesn't hurt to also remove the named entry as well.
|
||||||
|
// TODO: Since UUIDs are fixed, we could look up the name and see if the UUID matches.
|
||||||
|
jedisCluster.hdel("uuid-cache", entry.getName());
|
||||||
|
} else {
|
||||||
|
nameToUuidMap.put(entry.getName().toLowerCase(), entry);
|
||||||
|
uuidToNameMap.put(player, entry);
|
||||||
|
return entry.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expensiveLookups || !plugin.isOnlineMode())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// That didn't work. Let's ask Mojang. This call may fail, because Mojang is insane.
|
||||||
|
String name;
|
||||||
|
try {
|
||||||
|
List<String> nameHist = NameFetcher.nameHistoryFromUuid(player);
|
||||||
|
name = Iterables.getLast(nameHist, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.logFatal("Unable to fetch name from Mojang for " + player);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name != null) {
|
||||||
|
persistInfo(name, player, jedisCluster);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Okay, it wasn't locally cached. Let's try Redis.
|
||||||
|
try {
|
||||||
|
return redisTask.execute();
|
||||||
} catch (JedisException e) {
|
} catch (JedisException e) {
|
||||||
plugin.logFatal("Unable to fetch name for " + player);
|
plugin.logFatal("Unable to fetch name for " + player);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void persistInfo(String name, UUID uuid, Jedis jedis) {
|
public void persistInfo(String name, UUID uuid, Jedis jedis) {
|
||||||
addToMaps(name, uuid);
|
addToMaps(name, uuid);
|
||||||
String json = gson.toJson(uuidToNameMap.get(uuid));
|
String json = gson.toJson(uuidToNameMap.get(uuid));
|
||||||
jedis.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
|
jedis.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void persistInfo(String name, UUID uuid, Pipeline jedis) {
|
public void persistInfo(String name, UUID uuid, JedisCluster jedisCluster) {
|
||||||
addToMaps(name, uuid);
|
addToMaps(name, uuid);
|
||||||
String json = gson.toJson(uuidToNameMap.get(uuid));
|
String json = gson.toJson(uuidToNameMap.get(uuid));
|
||||||
jedis.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
|
jedisCluster.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CachedUUIDEntry {
|
private static class CachedUUIDEntry {
|
||||||
|
@ -11,7 +11,6 @@ import com.imaginarycode.minecraft.redisbungee.internal.AbstractDataManager;
|
|||||||
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.RedisUtil;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisUtil;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.util.RedisCallable;
|
|
||||||
import net.md_5.bungee.api.AbstractReconnectHandler;
|
import net.md_5.bungee.api.AbstractReconnectHandler;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
@ -21,6 +20,7 @@ import net.md_5.bungee.api.plugin.Listener;
|
|||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.event.EventHandler;
|
import net.md_5.bungee.event.EventHandler;
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisCluster;
|
||||||
import redis.clients.jedis.Pipeline;
|
import redis.clients.jedis.Pipeline;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@ -125,6 +125,11 @@ public class RedisBungeeBungeeListener extends AbstractRedisBungeeListener<Login
|
|||||||
new AbstractDataManager.ServerChangePayload(event.getServer().getInfo().getName(), currentServer))));
|
new AbstractDataManager.ServerChangePayload(event.getServer().getInfo().getName(), currentServer))));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void call(JedisCluster jedisCluster) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetwork
|
|||||||
import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
|
import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.*;
|
import com.imaginarycode.minecraft.redisbungee.internal.*;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.summoners.JedisSummoner;
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.Summoner;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.summoners.SinglePoolJedisSummoner;
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.SinglePoolJedisSummoner;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.util.IOUtil;
|
import com.imaginarycode.minecraft.redisbungee.internal.util.IOUtil;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.util.LuaManager;
|
import com.imaginarycode.minecraft.redisbungee.internal.util.LuaManager;
|
||||||
@ -48,7 +48,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||||||
public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin<ProxiedPlayer> {
|
public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin<ProxiedPlayer> {
|
||||||
private RedisBungeeAPI api;
|
private RedisBungeeAPI api;
|
||||||
private PubSubListener psl = null;
|
private PubSubListener psl = null;
|
||||||
private JedisSummoner jedisSummoner;
|
private Summoner jedisSummoner;
|
||||||
private UUIDTranslator uuidTranslator;
|
private UUIDTranslator uuidTranslator;
|
||||||
private RedisBungeeConfiguration configuration;
|
private RedisBungeeConfiguration configuration;
|
||||||
private BungeeDataManager dataManager;
|
private BungeeDataManager dataManager;
|
||||||
@ -503,7 +503,7 @@ public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JedisSummoner getJedisSummoner() {
|
public Summoner getSummoner() {
|
||||||
return this.jedisSummoner;
|
return this.jedisSummoner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ import com.imaginarycode.minecraft.redisbungee.internal.AbstractDataManager;
|
|||||||
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.RedisUtil;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisUtil;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.util.RedisCallable;
|
|
||||||
import com.velocitypowered.api.event.Continuation;
|
import com.velocitypowered.api.event.Continuation;
|
||||||
import com.velocitypowered.api.event.PostOrder;
|
import com.velocitypowered.api.event.PostOrder;
|
||||||
import com.velocitypowered.api.event.ResultedEvent;
|
import com.velocitypowered.api.event.ResultedEvent;
|
||||||
|
@ -13,7 +13,7 @@ import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetwork
|
|||||||
import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
|
import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.*;
|
import com.imaginarycode.minecraft.redisbungee.internal.*;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.summoners.JedisSummoner;
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.Summoner;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.summoners.SinglePoolJedisSummoner;
|
import com.imaginarycode.minecraft.redisbungee.internal.summoners.SinglePoolJedisSummoner;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.util.IOUtil;
|
import com.imaginarycode.minecraft.redisbungee.internal.util.IOUtil;
|
||||||
import com.imaginarycode.minecraft.redisbungee.internal.util.LuaManager;
|
import com.imaginarycode.minecraft.redisbungee.internal.util.LuaManager;
|
||||||
@ -61,7 +61,7 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
|
|||||||
private final Path dataFolder;
|
private final Path dataFolder;
|
||||||
private final RedisBungeeAPI api;
|
private final RedisBungeeAPI api;
|
||||||
private final PubSubListener psl;
|
private final PubSubListener psl;
|
||||||
private JedisSummoner jedisSummoner;
|
private Summoner jedisSummoner;
|
||||||
private final UUIDTranslator uuidTranslator;
|
private final UUIDTranslator uuidTranslator;
|
||||||
private RedisBungeeConfiguration configuration;
|
private RedisBungeeConfiguration configuration;
|
||||||
private final VelocityDataManager dataManager;
|
private final VelocityDataManager dataManager;
|
||||||
@ -201,7 +201,7 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JedisSummoner getJedisSummoner() {
|
public Summoner getSummoner() {
|
||||||
return this.jedisSummoner;
|
return this.jedisSummoner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user