diff --git a/src/main/java/org/redkale/cache/CacheManager.java b/src/main/java/org/redkale/cache/CacheManager.java index 0baf12436..2f46a39de 100644 --- a/src/main/java/org/redkale/cache/CacheManager.java +++ b/src/main/java/org/redkale/cache/CacheManager.java @@ -53,7 +53,7 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 @@ -68,7 +68,7 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 @@ -83,7 +83,7 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 */ public void localSet(String hash, String key, Type type, T value, Duration expire); @@ -93,7 +93,7 @@ public interface CacheManager { * @param hash 缓存hash * @param key 缓存键 * @param value 数据值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 */ default void localSetString(final String hash, final String key, final String value, Duration expire) { localSet(hash, key, String.class, value, expire); @@ -166,7 +166,7 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 @@ -182,7 +182,7 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 @@ -198,7 +198,7 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 */ public void remoteSet(final String hash, final String key, final Type type, final T value, Duration expire); @@ -208,7 +208,7 @@ public interface CacheManager { * @param hash 缓存hash * @param key 缓存键 * @param value 数据值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 */ default void remoteSetString(final String hash, final String key, final String value, Duration expire) { remoteSet(hash, key, String.class, value, expire); @@ -222,7 +222,9 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 + * + * @return void */ public CompletableFuture remoteSetAsync(String hash, String key, Type type, T value, Duration expire); @@ -232,7 +234,9 @@ public interface CacheManager { * @param hash 缓存hash * @param key 缓存键 * @param value 数据值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 + * + * @return void */ default CompletableFuture remoteSetStringAsync(final String hash, final String key, final String value, Duration expire) { return remoteSetAsync(hash, key, String.class, value, expire); @@ -315,8 +319,8 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 * @param supplier 数据函数 * * @return 数据值 @@ -332,8 +336,8 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 * @param supplier 数据函数 * * @return 数据值 @@ -349,8 +353,8 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 */ public void bothSet(final String hash, final String key, final Type type, final T value, Duration localExpire, Duration remoteExpire); @@ -360,8 +364,8 @@ public interface CacheManager { * @param hash 缓存hash * @param key 缓存键 * @param value 数据值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 */ default void bothSetString(final String hash, final String key, final String value, Duration localExpire, Duration remoteExpire) { bothSet(hash, key, String.class, value, localExpire, remoteExpire); @@ -375,8 +379,10 @@ public interface CacheManager { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 + * + * @return void */ public CompletableFuture bothSetAsync(String hash, String key, Type type, T value, Duration localExpire, Duration remoteExpire); @@ -386,8 +392,10 @@ public interface CacheManager { * @param hash 缓存hash * @param key 缓存键 * @param value 数据值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 + * + * @return void */ default CompletableFuture bothSetStringAsync(String hash, String key, String value, Duration localExpire, Duration remoteExpire) { return bothSetAsync(hash, key, String.class, value, localExpire, remoteExpire); diff --git a/src/main/java/org/redkale/cache/Cached.java b/src/main/java/org/redkale/cache/Cached.java index 6606f08d4..f4f5f8d20 100644 --- a/src/main/java/org/redkale/cache/Cached.java +++ b/src/main/java/org/redkale/cache/Cached.java @@ -16,8 +16,9 @@ import java.util.concurrent.TimeUnit; * * 标记在Service的缓存接口, 方法有以下限制:
* 1、方法返回类型不能是void/CompletableFuture<Void> - * 2、方法必须是protected/public - * 3、方法不能是final + * 2、方法返回类型必须可json序列化 + * 3、方法必须是protected/public + * 4、方法不能是final * * @since 2.8.0 */ @@ -35,7 +36,7 @@ public @interface Cached { String key(); /** - * 缓存的hash, 默认值用当前Service类的SimpleName + * 缓存的hash, 默认值用当前Service类的SimpleName, 不能含有':'、'#'、'@'字符 * * @return hash */ diff --git a/src/main/java/org/redkale/cache/support/CacheExpire.java b/src/main/java/org/redkale/cache/support/CacheExpire.java index 2ffaab9bc..6b4132630 100644 --- a/src/main/java/org/redkale/cache/support/CacheExpire.java +++ b/src/main/java/org/redkale/cache/support/CacheExpire.java @@ -15,7 +15,6 @@ import org.redkale.convert.json.JsonConvert; * 详情见: https://redkale.org * * @author zhangjx - * @param 泛型 * * @since 2.8.0 */ diff --git a/src/main/java/org/redkale/cache/support/CacheManagerService.java b/src/main/java/org/redkale/cache/support/CacheManagerService.java index fd7e9d2f4..52db22ed8 100644 --- a/src/main/java/org/redkale/cache/support/CacheManagerService.java +++ b/src/main/java/org/redkale/cache/support/CacheManagerService.java @@ -4,7 +4,6 @@ package org.redkale.cache.support; import java.lang.reflect.Type; -import java.math.BigDecimal; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -53,7 +52,7 @@ public class CacheManagerService implements CacheManager, Service { private final ConcurrentHashMap cacheValueTypes = new ConcurrentHashMap<>(); //本地缓存Source - protected final CacheMemorySource localSource = new CacheMemorySource("caching"); + protected final CacheMemorySource localSource = new CacheMemorySource("cache-local"); //缓存hash集合, 用于定时遍历删除过期数据 protected final ConcurrentSkipListSet hashNames = new ConcurrentSkipListSet<>(); @@ -142,9 +141,10 @@ public class CacheManagerService implements CacheManager, Service { */ @Override public T localGet(final String hash, final String key, final Type type) { - Type t = loadCacheType(type); - CacheValue val = localSource.hget(hash, key, t); - return CacheValue.get(val); + checkEnable(); + Type cacheType = loadCacheType(type); + CacheValue cacheVal = localSource.hget(hash, key, cacheType); + return CacheValue.get(cacheVal); } /** @@ -155,7 +155,7 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 @@ -172,7 +172,7 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 @@ -190,13 +190,15 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 */ @Override public void localSet(String hash, String key, Type type, T value, Duration expire) { - Type t = loadCacheType(type, value); - CacheValue val = CacheValue.create(value, expire); - localSource.hset(hash, key, t, val); + checkEnable(); + Objects.requireNonNull(expire); + Type cacheType = loadCacheType(type, value); + CacheValue cacheVal = CacheValue.create(value, expire); + localSource.hset(hash, key, cacheType, cacheVal); } /** @@ -209,6 +211,7 @@ public class CacheManagerService implements CacheManager, Service { */ @Override public long localDel(String hash, String key) { + checkEnable(); return localSource.hdel(hash, key); } @@ -225,9 +228,10 @@ public class CacheManagerService implements CacheManager, Service { */ @Override public T remoteGet(final String hash, final String key, final Type type) { - Type t = loadCacheType(type); - CacheValue val = remoteSource.hget(hash, key, t); - return CacheValue.get(val); + checkEnable(); + Type cacheType = loadCacheType(type); + CacheValue cacheVal = remoteSource.hget(hash, key, cacheType); + return CacheValue.get(cacheVal); } /** @@ -242,8 +246,9 @@ public class CacheManagerService implements CacheManager, Service { */ @Override public CompletableFuture remoteGetAsync(final String hash, final String key, final Type type) { - Type t = loadCacheType(type); - CompletableFuture> future = remoteSource.hgetAsync(hash, key, t); + checkEnable(); + Type cacheType = loadCacheType(type); + CompletableFuture> future = remoteSource.hgetAsync(hash, key, cacheType); return future.thenApply(CacheValue::get); } @@ -255,7 +260,7 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 @@ -272,7 +277,7 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 @@ -289,12 +294,14 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 */ public void remoteSet(final String hash, final String key, final Type type, final T value, Duration expire) { - Type t = loadCacheType(type, value); - CacheValue val = CacheValue.create(value, expire); - remoteSource.hset(hash, key, t, val); + checkEnable(); + Objects.requireNonNull(expire); + Type cacheType = loadCacheType(type, value); + CacheValue cacheVal = CacheValue.create(value, expire); + remoteSource.hset(hash, key, cacheType, cacheVal); } /** @@ -305,12 +312,14 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 */ public CompletableFuture remoteSetAsync(String hash, String key, Type type, T value, Duration expire) { - Type t = loadCacheType(type, value); - CacheValue val = CacheValue.create(value, expire); - return remoteSource.hsetAsync(hash, key, t, val); + checkEnable(); + Objects.requireNonNull(expire); + Type cacheType = loadCacheType(type, value); + CacheValue cacheVal = CacheValue.create(value, expire); + return remoteSource.hsetAsync(hash, key, cacheType, cacheVal); } /** @@ -322,6 +331,7 @@ public class CacheManagerService implements CacheManager, Service { * @return 删除数量 */ public long remoteDel(String hash, String key) { + checkEnable(); return remoteSource.hdel(hash, key); } @@ -334,6 +344,7 @@ public class CacheManagerService implements CacheManager, Service { * @return 删除数量 */ public CompletableFuture remoteDelAsync(String hash, String key) { + checkEnable(); return remoteSource.hdelAsync(hash, key); } @@ -377,18 +388,26 @@ public class CacheManagerService implements CacheManager, Service { * @param type 数据类型 * * @param nullable 是否缓存null值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 * @param supplier 数据函数 * * @return 数据值 */ @Override - public T bothGet(final String hash, final String key, final Type type, boolean nullable, Duration localExpire, Duration remoteExpire, Supplier supplier) { + public T bothGet(final String hash, final String key, final Type type, boolean nullable, + Duration localExpire, Duration remoteExpire, Supplier supplier) { + if (localExpire == null) { //只有远程缓存 + Objects.requireNonNull(remoteExpire); + return remoteGet(hash, key, type, nullable, remoteExpire, supplier); + } + if (remoteExpire == null) { //只有本地缓存 + return localGet(hash, key, type, nullable, localExpire, supplier); + } return get(this::bothGetCache, (h, k, t, v) -> { - localSource.hset(key, key, type, v); + localSource.hset(h, k, t, v); if (remoteSource != null) { - remoteSource.hset(hash, key, t, CacheValue.create(v.getValue(), remoteExpire)); + remoteSource.hset(h, k, t, CacheValue.create(v.getValue(), remoteExpire)); } }, hash, key, type, nullable, localExpire, supplier); } @@ -401,18 +420,26 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 * @param supplier 数据函数 * * @return 数据值 */ @Override - public CompletableFuture bothGetAsync(String hash, String key, Type type, boolean nullable, Duration localExpire, Duration remoteExpire, Supplier> supplier) { + public CompletableFuture bothGetAsync(String hash, String key, Type type, boolean nullable, + Duration localExpire, Duration remoteExpire, Supplier> supplier) { + if (localExpire == null) { //只有远程缓存 + Objects.requireNonNull(remoteExpire); + return remoteGetAsync(hash, key, type, nullable, remoteExpire, supplier); + } + if (remoteExpire == null) { //只有本地缓存 + return localGetAsync(hash, key, type, nullable, localExpire, supplier); + } return getAsync(this::bothGetCacheAsync, (h, k, t, v) -> { - localSource.hset(key, key, type, v); + localSource.hset(h, k, t, v); if (remoteSource != null) { - return remoteSource.hsetAsync(hash, key, t, CacheValue.create(v.getValue(), remoteExpire)); + return remoteSource.hsetAsync(h, k, t, CacheValue.create(v.getValue(), remoteExpire)); } else { return CompletableFuture.completedFuture(null); } @@ -427,20 +454,18 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 */ public void bothSet(final String hash, final String key, final Type type, final T value, Duration localExpire, Duration remoteExpire) { - Type t = loadCacheType(type, value); - localSource.hset(hash, key, t, CacheValue.create(value, localExpire)); - if (remoteSource != null) { - remoteSource.hset(hash, key, t, CacheValue.create(value, remoteExpire)); + checkEnable(); + Type cacheType = loadCacheType(type, value); + if (localExpire != null) { + localSource.hset(hash, key, cacheType, CacheValue.create(value, localExpire)); + } + if (remoteSource != null && remoteExpire != null) { + remoteSource.hset(hash, key, cacheType, CacheValue.create(value, remoteExpire)); } - } - - public static void main(String[] args) throws Throwable { - BigDecimal z = new BigDecimal("0"); - System.out.println(Objects.equals(BigDecimal.ZERO, z)); } /** @@ -451,14 +476,19 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param value 数据值 - * @param localExpire 本地过期时长,为null表示永不过期 - * @param remoteExpire 远程过期时长,为null表示永不过期 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 + * + * @return void */ public CompletableFuture bothSetAsync(String hash, String key, Type type, T value, Duration localExpire, Duration remoteExpire) { - Type t = loadCacheType(type, value); - localSource.hset(hash, key, t, CacheValue.create(value, localExpire)); - if (remoteSource != null) { - return remoteSource.hsetAsync(hash, key, t, CacheValue.create(value, remoteExpire)); + checkEnable(); + Type cacheType = loadCacheType(type, value); + if (localExpire != null) { + localSource.hset(hash, key, cacheType, CacheValue.create(value, localExpire)); //内存操作,无需异步 + } + if (remoteSource != null && remoteExpire != null) { + return remoteSource.hsetAsync(hash, key, cacheType, CacheValue.create(value, remoteExpire)); } else { return CompletableFuture.completedFuture(null); } @@ -473,6 +503,7 @@ public class CacheManagerService implements CacheManager, Service { * @return 删除数量 */ public long bothDel(String hash, String key) { + checkEnable(); long v = localSource.hdel(hash, key); if (remoteSource != null) { return remoteSource.hdel(hash, key); @@ -490,7 +521,8 @@ public class CacheManagerService implements CacheManager, Service { * @return 删除数量 */ public CompletableFuture bothDelAsync(String hash, String key) { - long v = localSource.hdel(hash, key); + checkEnable(); + long v = localSource.hdel(hash, key); //内存操作,无需异步 if (remoteSource != null) { return remoteSource.hdelAsync(hash, key); } else { @@ -509,34 +541,36 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 */ protected T get(GetterFunc> getter, SetterSyncFunc setter, String hash, String key, Type type, boolean nullable, Duration expire, Supplier supplier) { + checkEnable(); + Objects.requireNonNull(expire); Objects.requireNonNull(supplier); - final Type t = loadCacheType(type); - CacheValue val = getter.apply(hash, key, t); - if (CacheValue.isValid(val)) { - return val.getValue(); + final Type cacheType = loadCacheType(type); + CacheValue cacheVal = getter.get(hash, key, type); + if (CacheValue.isValid(cacheVal)) { + return cacheVal.getValue(); } Function func = k -> { - CacheValue oldVal = getter.apply(hash, key, t); - if (CacheValue.isValid(oldVal)) { - return oldVal; + CacheValue oldCacheVal = getter.get(hash, key, type); + if (CacheValue.isValid(oldCacheVal)) { + return oldCacheVal; } - CacheValue newVal = toCacheSupplier(nullable, expire, supplier).get(); - if (CacheValue.isValid(newVal)) { - setter.apply(hash, key, t, newVal); + CacheValue newCacheVal = toCacheSupplier(nullable, expire, supplier).get(); + if (CacheValue.isValid(newCacheVal)) { + setter.set(hash, key, cacheType, newCacheVal); } - return newVal; + return newCacheVal; }; final String lockId = lockId(hash, key); - val = syncLock.computeIfAbsent(lockId, func); + cacheVal = syncLock.computeIfAbsent(lockId, func); try { - return CacheValue.get(val); + return CacheValue.get(cacheVal); } finally { syncLock.remove(lockId); } @@ -552,16 +586,17 @@ public class CacheManagerService implements CacheManager, Service { * @param key 缓存键 * @param type 数据类型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return 数据值 */ protected CompletableFuture getAsync(GetterFunc>> getter, SetterAsyncFunc setter, String hash, String key, Type type, boolean nullable, Duration expire, Supplier> supplier) { + checkEnable(); Objects.requireNonNull(supplier); - final Type t = loadCacheType(type); - CompletableFuture> sourceFuture = getter.apply(hash, key, t); + final Type cacheType = loadCacheType(type); + CompletableFuture> sourceFuture = getter.get(hash, key, type); return sourceFuture.thenCompose(val -> { if (CacheValue.isValid(val)) { return CompletableFuture.completedFuture(val.getValue()); @@ -575,12 +610,12 @@ public class CacheManagerService implements CacheManager, Service { if (e != null) { entry.fail(e); } - CacheValue rs = toCacheValue(nullable, expire, v); - if (CacheValue.isValid(val)) { - setter.apply(hash, key, t, val) - .whenComplete((v2, e2) -> entry.success(CacheValue.get(rs))); + CacheValue cacheVal = toCacheValue(nullable, expire, v); + if (CacheValue.isValid(cacheVal)) { + setter.set(hash, key, cacheType, cacheVal) + .whenComplete((v2, e2) -> entry.success(CacheValue.get(cacheVal))); } else { - entry.success(CacheValue.get(rs)); + entry.success(CacheValue.get(cacheVal)); } }); } catch (Throwable e) { @@ -592,13 +627,14 @@ public class CacheManagerService implements CacheManager, Service { } protected CacheValue bothGetCache(final String hash, final String key, final Type type) { - Type t = loadCacheType(type); - CacheValue val = localSource.hget(hash, key, t); - if (CacheValue.isValid(val)) { - return val; + checkEnable(); + Type cacheType = loadCacheType(type); + CacheValue cacheVal = localSource.hget(hash, key, cacheType); + if (CacheValue.isValid(cacheVal)) { + return cacheVal; } if (remoteSource != null) { - return remoteSource.hget(hash, key, t); + return remoteSource.hget(hash, key, cacheType); } else { return null; } @@ -615,35 +651,43 @@ public class CacheManagerService implements CacheManager, Service { * @return 数据值 */ protected CompletableFuture> bothGetCacheAsync(final String hash, final String key, final Type type) { - Type t = loadCacheType(type); - CacheValue val = localSource.hget(hash, key, t); + checkEnable(); + Type cacheType = loadCacheType(type); + CacheValue val = localSource.hget(hash, key, cacheType); //内存操作,无需异步 if (CacheValue.isValid(val)) { return CompletableFuture.completedFuture(val); } if (remoteSource != null) { - return remoteSource.hgetAsync(hash, key, t); + return remoteSource.hgetAsync(hash, key, cacheType); } else { return CompletableFuture.completedFuture(null); } } + protected void checkEnable() { + if (!enabled) { + throw new RedkaleException(CacheManager.class.getSimpleName() + " is disabled"); + } + } + /** * 创建一个锁key * * @param hash 缓存hash * @param key 缓存键 * - * @return + * @return key */ protected String lockId(String hash, String key) { - return hash + (char) 8 + key; + return hash + ':' + key; } /** * 将原始数据函数转换成获取CacheValue数据函数 * + * @param 泛型 * @param nullable 是否缓存null值 - * @param expire 过期时长,为null表示永不过期 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param value 缓存值 * * @return CacheValue函数 @@ -658,7 +702,9 @@ public class CacheManagerService implements CacheManager, Service { /** * 将原始数据函数转换成获取CacheValue数据函数 * - * @param expire 过期时长,为null表示永不过期 + * @param 泛型 + * @param nullable 是否缓存null值 + * @param expire 过期时长,Duration.ZERO为永不过期 * @param supplier 数据函数 * * @return CacheValue函数 @@ -694,17 +740,17 @@ public class CacheManagerService implements CacheManager, Service { protected static interface GetterFunc { - public R apply(String hash, String key, Type type); + public R get(String hash, String key, Type type); } protected static interface SetterSyncFunc { - public void apply(String hash, String key, Type type, CacheValue value); + public void set(String hash, String key, Type cacheType, CacheValue cacheVal); } protected static interface SetterAsyncFunc { - public CompletableFuture apply(String hash, String key, Type type, CacheValue value); + public CompletableFuture set(String hash, String key, Type cacheType, CacheValue cacheVal); } protected class CacheAsyncEntry { diff --git a/src/test/java/org/redkale/test/cache/CacheManagerTest.java b/src/test/java/org/redkale/test/cache/CacheManagerTest.java new file mode 100644 index 000000000..db25f7e8c --- /dev/null +++ b/src/test/java/org/redkale/test/cache/CacheManagerTest.java @@ -0,0 +1,129 @@ +/* + * + */ +package org.redkale.test.cache; + +import java.time.Duration; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.*; +import org.redkale.cache.support.CacheManagerService; +import org.redkale.convert.json.JsonConvert; +import org.redkale.source.CacheMemorySource; +import org.redkale.util.Utility; + +/** + * + * @author zhangjx + */ +public class CacheManagerTest { + + private static CacheManagerService manager; + + public static void main(String[] args) throws Throwable { + CacheManagerTest test = new CacheManagerTest(); + test.init(); + test.run1(); + test.run2(); + } + + @BeforeAll + public static void init() throws Exception { + CacheMemorySource remoteSource = new CacheMemorySource("cache-remote"); + remoteSource.init(null); + manager = CacheManagerService.create(remoteSource); + manager.init(null); + } + + @Test + public void run1() throws Exception { + Duration expire = Duration.ofMillis(290); + manager.localSetString("user", "name:haha", "myha", expire); + Assertions.assertEquals(manager.localGetString("user", "name:haha"), "myha"); + Utility.sleep(300); + Assertions.assertTrue(manager.localGetString("user", "name:haha") == null); + + CachingBean bean = new CachingBean(); + bean.setName("tom"); + bean.setRemark("这是名字备注"); + + String json = bean.toString(); + manager.localSet("user", bean.getName(), CachingBean.class, bean, expire); + Assertions.assertEquals(manager.localGet("user", bean.getName(), CachingBean.class).toString(), json); + bean.setRemark(bean.getRemark() + "-新备注"); + Assertions.assertEquals(manager.localGet("user", bean.getName(), CachingBean.class).toString(), json); + } + + @Test + public void run2() throws Exception { + int count = 50; + ParallelBean bean = new ParallelBean(); + Duration localExpire = Duration.ofMillis(190); + Duration remoteExpire = Duration.ofMillis(400); + { + CountDownLatch cdl = new CountDownLatch(count); + for (int i = 0; i < count; i++) { + new Thread(() -> { + manager.bothGet("ParallelBean", "name", String.class, false, localExpire, remoteExpire, () -> bean.getName()); + cdl.countDown(); + }).start(); + } + cdl.await(); + } + Assertions.assertEquals(1, ParallelBean.c1.get()); + Utility.sleep(200); + manager.bothGet("ParallelBean", "name", String.class, false, localExpire, remoteExpire, () -> bean.getName()); + Assertions.assertEquals(1, ParallelBean.c1.get()); + Utility.sleep(200); + { + CountDownLatch cdl = new CountDownLatch(count); + for (int i = 0; i < count; i++) { + new Thread(() -> { + manager.bothGet("ParallelBean", "name", String.class, false, localExpire, remoteExpire, () -> bean.getName()); + cdl.countDown(); + }).start(); + } + cdl.await(); + } + Assertions.assertEquals(2, ParallelBean.c1.get()); + + } + + public static class ParallelBean { + + public static final AtomicInteger c1 = new AtomicInteger(); + + public String getName() { + c1.incrementAndGet(); + System.out.println("执行了getName方法(" + c1.get() + ")"); + return "hello"; + } + } + + public static class CachingBean { + + private String name; + + private String remark; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public String toString() { + return JsonConvert.root().convertTo(this); + } + } +} diff --git a/src/test/java/org/redkale/test/cache/CachingTest.java b/src/test/java/org/redkale/test/cache/CachingTest.java deleted file mode 100644 index b8903ebc4..000000000 --- a/src/test/java/org/redkale/test/cache/CachingTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - */ -package org.redkale.test.cache; - -import java.time.Duration; -import org.junit.jupiter.api.*; -import org.redkale.cache.support.CacheManagerService; -import org.redkale.convert.json.JsonConvert; -import org.redkale.source.CacheMemorySource; -import org.redkale.util.Utility; -/** - * - * @author zhangjx - */ -public class CachingTest { - - private static CacheManagerService manager; - - public static void main(String[] args) throws Throwable { - CachingTest test = new CachingTest(); - test.wait(); - test.run(); - } - - @BeforeAll - public static void init() throws Exception { - CacheMemorySource remoteSource = new CacheMemorySource("remote"); - remoteSource.init(null); - manager = CacheManagerService.create(remoteSource); - manager.init(null); - } - - @Test - public void run() throws Exception { - Duration expire = Duration.ofMillis(490); - manager.localSetString("user", "name:haha", "myha", expire); - Assertions.assertEquals(manager.localGetString("user", "name:haha"), "myha"); - Utility.sleep(500); - Assertions.assertTrue(manager.localGetString("user", "name:haha") == null); - - CachingBean bean = new CachingBean(); - bean.setName("tom"); - bean.setRemark("这是名字备注"); - - String json = bean.toString(); - manager.localSet("user", bean.getName(), CachingBean.class, bean, expire); - Assertions.assertEquals(manager.localGet("user", bean.getName(), CachingBean.class).toString(), json); - bean.setRemark(bean.getRemark() + "-新备注"); - Assertions.assertEquals(manager.localGet("user", bean.getName(), CachingBean.class).toString(), json); - manager.destroy(null); - } - - public static class CachingBean { - - private String name; - - private String remark; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getRemark() { - return remark; - } - - public void setRemark(String remark) { - this.remark = remark; - } - - public String toString() { - return JsonConvert.root().convertTo(this); - } - } -}