diff --git a/common/src/main/java/online/mineroo/common/cache/UserInfoCache.java b/common/src/main/java/online/mineroo/common/cache/UserInfoCache.java index 28b6906..decdd0f 100644 --- a/common/src/main/java/online/mineroo/common/cache/UserInfoCache.java +++ b/common/src/main/java/online/mineroo/common/cache/UserInfoCache.java @@ -1,15 +1,24 @@ package online.mineroo.common.cache; +import java.time.Duration; import java.time.LocalDateTime; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import online.mineroo.common.request.UserRequest.SimpleUserInfoResponse; public class UserInfoCache { - private ConcurrentHashMap uuidMap = new ConcurrentHashMap<>(); - private ConcurrentHashMap simpleUserInfo = new ConcurrentHashMap<>(); + private final ConcurrentHashMap uuidMap = new ConcurrentHashMap<>(); + private final ConcurrentHashMap simpleUserInfo = new ConcurrentHashMap<>(); + + private final Duration cacheTtl; - public UserInfoCache() {} + public UserInfoCache() { + this(Duration.ofHours(24)); + } + + public UserInfoCache(Duration cacheTtl) { + this.cacheTtl = cacheTtl != null ? cacheTtl : Duration.ofHours(24); + } public UUID insert(UUID uuid, SimpleUserInfoResponse simpleUserInfoResponse) { this.simpleUserInfo.put(uuid, new SimpleUserCacheInfo(simpleUserInfoResponse)); @@ -32,10 +41,11 @@ public class UserInfoCache { return null; } - // LocalDateTime expireTime = info.getTime().plusHours(24); - // if (LocalDateTime.now().isAfter(expireTime)) { - // return null; - // } + if (info.isExpired(cacheTtl)) { + this.simpleUserInfo.remove(uuid); + this.uuidMap.values().removeIf(val -> val.equals(uuid)); + return null; + } return info.getData(); } @@ -52,6 +62,11 @@ public class UserInfoCache { return this.get(uuid); } + public SimpleUserInfoResponse getIfPresent(UUID uuid) { + SimpleUserCacheInfo info = this.simpleUserInfo.get(uuid); + return info != null ? info.getData() : null; + } + public void remove(UUID uuid) { if (uuid == null) { return; @@ -67,30 +82,50 @@ public class UserInfoCache { } public void cleanup() { - // LocalDateTime now = LocalDateTime.now(); - // - // simpleUserInfo.entrySet().removeIf(entry -> { - // return now.isAfter(entry.getValue().getTime().plusHours(24)); - // }); - // - // uuidMap.entrySet().removeIf(entry -> !simpleUserInfo.containsKey(entry.getValue())); + LocalDateTime now = LocalDateTime.now(); + + simpleUserInfo.entrySet().removeIf(entry -> { + boolean expired = entry.getValue().isExpiredAt(now, cacheTtl); + if (expired) { + uuidMap.values().removeIf(val -> val.equals(entry.getKey())); + } + return expired; + }); + } + + public int size() { + return simpleUserInfo.size(); + } + + public void clear() { + simpleUserInfo.clear(); + uuidMap.clear(); } public static class SimpleUserCacheInfo { - private SimpleUserInfoResponse data; - private LocalDateTime time; + private final SimpleUserInfoResponse data; + private final LocalDateTime createdAt; public SimpleUserCacheInfo(SimpleUserInfoResponse data) { this.data = data; - this.time = LocalDateTime.now(); + this.createdAt = LocalDateTime.now(); } public SimpleUserInfoResponse getData() { return this.data; } - public LocalDateTime getTime() { - return this.time; + public LocalDateTime getCreatedAt() { + return this.createdAt; + } + + public boolean isExpired(Duration ttl) { + return isExpiredAt(LocalDateTime.now(), ttl); + } + + public boolean isExpiredAt(LocalDateTime now, Duration ttl) { + LocalDateTime expireTime = createdAt.plus(ttl); + return now.isAfter(expireTime); } } } diff --git a/paper/src/main/java/online/mineroo/paper/MinerooCore.java b/paper/src/main/java/online/mineroo/paper/MinerooCore.java index 9a6c9d0..f36ece2 100644 --- a/paper/src/main/java/online/mineroo/paper/MinerooCore.java +++ b/paper/src/main/java/online/mineroo/paper/MinerooCore.java @@ -77,6 +77,14 @@ public class MinerooCore extends JavaPlugin implements Listener { long period = 20L * 90; scheduler.runTaskTimer(this, new ReportPlayersTask(this, scheduler), 20L * 30, period); } + + // Schedule cache cleanup task (every 10 minutes) + getServer().getScheduler().runTaskTimerAsynchronously(this, () -> { + if (this.userInfoCache != null) { + this.userInfoCache.cleanup(); + getLogger().fine("UserInfoCache cleanup completed, size: " + this.userInfoCache.size()); + } + }, 20L * 60 * 10, 20L * 60 * 10); // 10 minutes } @Override