109 lines
4.2 KiB
Java
109 lines
4.2 KiB
Java
package com.io.yutian.aulib.redis;
|
|
|
|
import com.io.yutian.aulib.AuLib;
|
|
import com.io.yutian.aulib.util.Pair;
|
|
import org.bukkit.plugin.Plugin;
|
|
import org.bukkit.scheduler.BukkitRunnable;
|
|
import org.bukkit.scheduler.BukkitTask;
|
|
import redis.clients.jedis.Jedis;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
public class RedisCacheSyncTimer {
|
|
|
|
private static final String LOCK_KEY = "sync_lock";
|
|
private static final int LOCK_EXPIRE_SECONDS = 300;
|
|
private final Map<Plugin, PluginInfo> pluginInfos = new HashMap<>();
|
|
|
|
private BukkitTask task;
|
|
|
|
public RedisCacheSyncTimer() {
|
|
task = new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
if (pluginInfos.isEmpty()) {
|
|
return;
|
|
}
|
|
for (Map.Entry<Plugin, PluginInfo> entry : pluginInfos.entrySet()) {
|
|
Plugin plugin = entry.getKey();
|
|
if (!plugin.isEnabled()) {
|
|
continue;
|
|
}
|
|
PluginInfo pluginInfo = entry.getValue();
|
|
String lockKey = LOCK_KEY + "_" + plugin.getName();
|
|
IJedisGetter jedisGetter = pluginInfo.getJedisGetter();
|
|
try (Jedis jedis = jedisGetter.getRedis()) {
|
|
long lockResult = jedis.setnx(lockKey, "locked");
|
|
if (lockResult != 1) {
|
|
continue;
|
|
}
|
|
jedis.expire(lockKey, LOCK_EXPIRE_SECONDS);
|
|
for (Map.Entry<Pair<String, String>, RedisCacheSynchronizer> entry1 : entry.getValue().getSynchronizers().entrySet()) {
|
|
Pair<String, String> key = entry1.getKey();
|
|
RedisCacheSynchronizer synchronizer = entry1.getValue();
|
|
String k1 = key.first();
|
|
String k2 = key.second();
|
|
for (String k : jedis.keys(k1+":*")) {
|
|
String data = null;
|
|
if (k2 == null) {
|
|
data = jedis.get(k);
|
|
} else {
|
|
data = jedis.hget(k, k2);
|
|
}
|
|
if (data != null) {
|
|
String finalData = data;
|
|
synchronizer.sync(k, finalData);
|
|
if (k2 == null) {
|
|
jedis.del(k);
|
|
} else {
|
|
jedis.hdel(k, k2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}.runTaskTimerAsynchronously(AuLib.inst(), 1200L, 5 * 60 * 20L);
|
|
}
|
|
|
|
public void registerSynchronizer(Plugin plugin, IJedisGetter jedisGetter, Pair<String, String> key, RedisCacheSynchronizer synchronizer) {
|
|
PluginInfo pluginInfo = pluginInfos.computeIfAbsent(plugin, k -> new PluginInfo(jedisGetter));
|
|
pluginInfo.addSynchronizer(key, synchronizer);
|
|
pluginInfos.put(plugin, pluginInfo);
|
|
}
|
|
|
|
class PluginInfo {
|
|
|
|
private IJedisGetter jedisGetter;
|
|
private Map<Pair<String, String>, RedisCacheSynchronizer> synchronizers;
|
|
|
|
public PluginInfo(IJedisGetter jedisGetter) {
|
|
this.jedisGetter = jedisGetter;
|
|
this.synchronizers = new HashMap<>();
|
|
}
|
|
|
|
public void addSynchronizer(Pair<String, String> key, RedisCacheSynchronizer synchronizer) {
|
|
if (key == null || synchronizer == null) {
|
|
return;
|
|
}
|
|
if (synchronizers.containsKey(key)) {
|
|
throw new IllegalArgumentException("Key already registered: " + key);
|
|
}
|
|
synchronizers.put(key, synchronizer);
|
|
}
|
|
|
|
public IJedisGetter getJedisGetter() {
|
|
return jedisGetter;
|
|
}
|
|
|
|
public Map<Pair<String, String>, RedisCacheSynchronizer> getSynchronizers() {
|
|
return synchronizers;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|