AuLib/src/main/java/com/io/yutian/aulib/redis/RedisCacheSyncTimer.java
2024-07-23 16:22:55 +08:00

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;
}
}
}