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 pluginInfos = new HashMap<>(); private BukkitTask task; public RedisCacheSyncTimer() { task = new BukkitRunnable() { @Override public void run() { if (pluginInfos.isEmpty()) { return; } for (Map.Entry 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, RedisCacheSynchronizer> entry1 : entry.getValue().getSynchronizers().entrySet()) { Pair 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 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, RedisCacheSynchronizer> synchronizers; public PluginInfo(IJedisGetter jedisGetter) { this.jedisGetter = jedisGetter; this.synchronizers = new HashMap<>(); } public void addSynchronizer(Pair 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, RedisCacheSynchronizer> getSynchronizers() { return synchronizers; } } }