diff --git a/conf/application.properties b/conf/application.properties new file mode 100644 index 0000000..3987050 --- /dev/null +++ b/conf/application.properties @@ -0,0 +1,13 @@ +redkale.name=zhub-dev +redkale.port=6560 +redkale.server[0].protocol=HTTP +redkale.server[0].host=127.0.0.1 +redkale.server[0].port=80 +# redkale.server[0].root = root +redkale.server[0].rest.autoload=true +redkale.server[0].rest.path= +redkale.server[0].services[0].autoload=true +# zhub +redkale.cluster.zhub[hub].addr=47.111.150.118:6066 +redkale.cluster.zhub[hub].auth=zchd@123456 +redkale.cluster.zhub[hub].groupid=venue-zhub \ No newline at end of file diff --git a/conf/application.xml b/conf/application.xml deleted file mode 100644 index 3c2e3ed..0000000 --- a/conf/application.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/conf/kafak.properties b/conf/kafak.properties deleted file mode 100644 index 37bcd72..0000000 --- a/conf/kafak.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Producer -#bootstrap.servers=47.111.150.118:6062 -#bootstrap.servers=121.196.17.55:6062 -bootstrap.servers=39.108.56.246:9092 -#bootstrap.servers=122.112.180.156:6062 -acks=all -retries=0 -batch.size=16384 -linger.ms=1 -buffer.memory=33554432 -key.serializer=org.apache.kafka.common.serialization.StringSerializer -value.serializer=org.apache.kafka.common.serialization.StringSerializer - -# Consumer -enable.auto.commit=true -auto.commit.interval.ms=1000 -group.id= -key.deserializer=org.apache.kafka.common.serialization.StringDeserializer -value.deserializer=org.apache.kafka.common.serialization.StringDeserializer \ No newline at end of file diff --git a/conf/logging.properties b/conf/logging.properties new file mode 100644 index 0000000..ab86219 --- /dev/null +++ b/conf/logging.properties @@ -0,0 +1,18 @@ +handlers=java.util.logging.ConsoleHandler +# handlers = java.util.logging.FileHandler +############################################################ +.level=FINEST +java.level=INFO +javax.level=INFO +com.sun.level=INFO +sun.level=INFO +jdk.level=INFO +java.util.logging.FileHandler.level=FINER +#10M +java.util.logging.FileHandler.limit=10M +java.util.logging.FileHandler.count=20 +java.util.logging.FileHandler.encoding=UTF-8 +java.util.logging.FileHandler.pattern=${APP_HOME}/logs-%tY%tm/log-%tY%tm%td.log +java.util.logging.FileHandler.unusual=${APP_HOME}/logs-%tY%tm/log-warnerr-%tY%tm%td.log +java.util.logging.FileHandler.append=true +java.util.logging.ConsoleHandler.level=FINEST diff --git a/conf/source.properties b/conf/source.properties new file mode 100644 index 0000000..741210c --- /dev/null +++ b/conf/source.properties @@ -0,0 +1,5 @@ +############ ClusterSource @Resource(name="hub") ############ +# redkale.cluster.zhub[hub].addr = 47.111.150.118:6066 +# redkale.cluster.zhub[hub].auth = zchd@123456 +# redkale.cluster.zhub[hub].groupid = venue-zhub + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..96d099f --- /dev/null +++ b/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + net.tccn + zhub-client-redkale + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + + \ No newline at end of file diff --git a/src/com/zdemo/ZhubListener.java b/src/com/zdemo/ZhubListener.java deleted file mode 100644 index 7db44f7..0000000 --- a/src/com/zdemo/ZhubListener.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.zdemo; - -import org.redkale.boot.Application; -import org.redkale.boot.ApplicationListener; -import org.redkale.service.Service; -import org.redkale.util.AnyValue; -import org.redkale.util.RedkaleClassLoader; -import org.redkale.util.ResourceFactory; - -import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.CompletableFuture; - -/** - * 服务监听 - * - * @author: liangxy. - */ -public class ZhubListener implements ApplicationListener { - - @Override - public void preStart(Application application) { - - CompletableFuture.runAsync(() -> { - ResourceFactory resourceFactory = application.getResourceFactory(); - RedkaleClassLoader classLoader = application.getClassLoader(); - - AnyValue appConfig = application.getAppConfig(); - AnyValue zhubs = appConfig.getAnyValue("zhubs"); - AnyValue[] values = zhubs.getAnyValues("zhub"); - for (AnyValue zhub : values) { - String className = zhub.getValue("value", "com.zdemo.zhub.ZHubClient"); - try { - Class clazz = classLoader.loadClass(className); - Service obj = (Service) clazz.getDeclaredConstructor().newInstance(); - application.getResourceFactory().inject(obj); - obj.init(zhub); - resourceFactory.register(zhub.get("name"), clazz, obj); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) { - e.printStackTrace(); - } - } - }); - } - - @Override - public void preShutdown(Application application) { - - } -} diff --git a/src/com/zdemo/cache_/RedisCacheSource.java b/src/com/zdemo/cache_/RedisCacheSource.java deleted file mode 100644 index 4bf837e..0000000 --- a/src/com/zdemo/cache_/RedisCacheSource.java +++ /dev/null @@ -1,2173 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.zdemo.cache_; - -import org.redkale.convert.Convert; -import org.redkale.convert.json.JsonConvert; -import org.redkale.convert.json.JsonFactory; -import org.redkale.net.AsyncConnection; -import org.redkale.net.Transport; -import org.redkale.net.TransportFactory; -import org.redkale.service.AbstractService; -import org.redkale.service.Local; -import org.redkale.service.Service; -import org.redkale.source.CacheSource; -import org.redkale.source.Flipper; -import org.redkale.util.*; -import org.redkale.util.AnyValue.DefaultAnyValue; - -import javax.annotation.Resource; -import java.io.IOException; -import java.io.Serializable; -import java.lang.reflect.Type; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.CompletionHandler; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Semaphore; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static org.redkale.boot.Application.RESNAME_APP_GROUP; - -/** - * 详情见: https://redkale.org - * - * @param Value - * @author zhangjx - */ -@Local -@AutoLoad(false) -@ResourceType(CacheSource.class) -public class RedisCacheSource extends AbstractService implements CacheSource, Service, AutoCloseable, Resourcable { - - protected static final byte DOLLAR_BYTE = '$'; - - protected static final byte ASTERISK_BYTE = '*'; - - protected static final byte PLUS_BYTE = '+'; - - protected static final byte MINUS_BYTE = '-'; - - protected static final byte COLON_BYTE = ':'; - - private final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - - @Resource(name = RESNAME_APP_GROUP) - protected AsyncGroup asyncGroup; - - @Resource - public JsonConvert defaultConvert; - - @Resource(name = "$_convert") - public JsonConvert convert; - - protected Type objValueType = String.class; - - protected Map passwords; - - protected List nodeAddrs; - - protected int db; - - protected Transport transport; - - @Override - public void init(AnyValue conf) { - if (this.convert == null) this.convert = this.defaultConvert; - if (conf == null) conf = new DefaultAnyValue(); - final int readTimeoutSeconds = conf.getIntValue("readTimeoutSeconds", TransportFactory.DEFAULT_READTIMEOUTSECONDS); - final int writeTimeoutSeconds = conf.getIntValue("writeTimeoutSeconds", TransportFactory.DEFAULT_WRITETIMEOUTSECONDS); - final List addresses = new ArrayList<>(); - Map passwords0 = new HashMap<>(); - for (AnyValue node : conf.getAnyValues("node")) { - String addrstr = node.getValue("addr"); - InetSocketAddress addr = null; - if (addrstr.startsWith("redis://")) { - addrstr = addrstr.substring("redis://".length()); - int pos = addrstr.indexOf(':'); - addr = new InetSocketAddress(addrstr.substring(0, pos), Integer.parseInt(addrstr.substring(pos + 1))); - addresses.add(addr); - } else { - addr = new InetSocketAddress(addrstr, node.getIntValue("port")); - addresses.add(addr); - } - String password = node.getValue("password", "").trim(); - if (!password.isEmpty()) passwords0.put(addr, password.getBytes(StandardCharsets.UTF_8)); - String db0 = node.getValue("db", "").trim(); - if (!db0.isEmpty()) this.db = Integer.valueOf(db0); - } - if (!passwords0.isEmpty()) this.passwords = passwords0; - this.nodeAddrs = addresses; - TransportFactory transportFactory = TransportFactory.create(asyncGroup, readTimeoutSeconds, writeTimeoutSeconds); - this.transport = transportFactory.createTransportTCP("Redis-Transport", null, addresses); - this.transport.setSemaphore(new Semaphore(conf.getIntValue("maxconns", 1000))); - if (logger.isLoggable(Level.FINE)) - logger.log(Level.FINE, RedisCacheSource.class.getSimpleName() + ": addrs=" + addresses + ", db=" + db); - - } - - @Override //ServiceLoader时判断配置是否符合当前实现类 - public boolean match(AnyValue config) { - if (config == null) return false; - AnyValue[] nodes = config.getAnyValues("node"); - if (nodes == null || nodes.length == 0) return false; - for (AnyValue node : nodes) { - if (node.getValue("addr") != null && node.getValue("port") != null) return true; - if (node.getValue("addr") != null && node.getValue("addr").startsWith("redis://")) return true; - } - return false; - } - - public void updateRemoteAddresses(final Collection addresses) { - this.transport.updateRemoteAddresses(addresses); - } - - @Override - @Deprecated - public final void initValueType(Type valueType) { - this.objValueType = valueType == null ? String.class : valueType; - } - - @Override - @Deprecated - public final void initTransient(boolean flag) { - } - - @Override - public final String getType() { - return "redis"; - } - - public static void main(String[] args) throws Exception { - DefaultAnyValue conf = new DefaultAnyValue().addValue("maxconns", "1"); - conf.addValue("node", new DefaultAnyValue().addValue("addr", "127.0.0.1").addValue("port", "6363")); - - final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16); - asyncGroup.start(); - ResourceFactory.root().register(RESNAME_APP_GROUP, asyncGroup); - - RedisCacheSource source = new RedisCacheSource(); - ResourceFactory.root().inject(source); - source.init(null); - source.defaultConvert = JsonFactory.root().getConvert(); - source.init(conf); - InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 7788); - try { - System.out.println("------------------------------------"); - source.removeAsync("stritem1"); - source.removeAsync("stritem2"); - source.setStringAsync("stritem1", "value1"); - source.setStringAsync("stritem2", "value2"); - System.out.println("stritem开头的key有两个: " + source.queryKeysStartsWith("stritem")); - System.out.println("[有值] MGET : " + source.getStringMap("stritem1", "stritem2")); - System.out.println("[有值] MGET : " + Arrays.toString(source.getStringArray("stritem1", "stritem2"))); - - source.remove("intitem1"); - source.remove("intitem2"); - source.setLong("intitem1", 333); - source.setLong("intitem2", 444); - System.out.println("[有值] MGET : " + source.getStringMap("intitem1", "intitem22", "intitem2")); - System.out.println("[有值] MGET : " + Arrays.toString(source.getStringArray("intitem1", "intitem22", "intitem2"))); - source.remove("objitem1"); - source.remove("objitem2"); - source.set("objitem1", Flipper.class, new Flipper(10)); - source.set("objitem2", Flipper.class, new Flipper(20)); - System.out.println("[有值] MGET : " + source.getMap(Flipper.class, "objitem1", "objitem2")); - - source.remove("key1"); - source.remove("key2"); - source.remove("300"); - source.set(1000, "key1", String.class, "value1"); - source.set("key1", String.class, "value1"); - source.setString("keystr1", "strvalue1"); - source.setLong("keylong1", 333L); - source.set("300", String.class, "4000"); - source.getAndRefresh("key1", 3500, String.class); - System.out.println("[有值] 300 GET : " + source.get("300", String.class)); - System.out.println("[有值] key1 GET : " + source.get("key1", String.class)); - System.out.println("[无值] key2 GET : " + source.get("key2", String.class)); - System.out.println("[有值] keystr1 GET : " + source.getString("keystr1")); - System.out.println("[有值] keylong1 GET : " + source.getLong("keylong1", 0L)); - System.out.println("[有值] key1 EXISTS : " + source.exists("key1")); - System.out.println("[无值] key2 EXISTS : " + source.exists("key2")); - - source.remove("keys3"); - source.appendListItem("keys3", String.class, "vals1"); - source.appendListItem("keys3", String.class, "vals2"); - System.out.println("-------- keys3 追加了两个值 --------"); - System.out.println("[两值] keys3 VALUES : " + source.getCollection("keys3", String.class)); - System.out.println("[有值] keys3 EXISTS : " + source.exists("keys3")); - source.removeListItem("keys3", String.class, "vals1"); - System.out.println("[一值] keys3 VALUES : " + source.getCollection("keys3", String.class)); - source.getCollectionAndRefresh("keys3", 3000, String.class); - - source.remove("stringmap"); - source.appendSetItem("stringmap", JsonConvert.TYPE_MAP_STRING_STRING, Utility.ofMap("a", "aa", "b", "bb")); - source.appendSetItem("stringmap", JsonConvert.TYPE_MAP_STRING_STRING, Utility.ofMap("c", "cc", "d", "dd")); - System.out.println("[两值] stringmap VALUES : " + source.getCollectionAsync("stringmap", JsonConvert.TYPE_MAP_STRING_STRING).join()); - - source.remove("sets3"); - source.remove("sets4"); - source.appendSetItem("sets3", String.class, "setvals1"); - source.appendSetItem("sets3", String.class, "setvals2"); - source.appendSetItem("sets3", String.class, "setvals1"); - source.appendSetItem("sets4", String.class, "setvals2"); - source.appendSetItem("sets4", String.class, "setvals1"); - System.out.println("[两值] sets3 VALUES : " + source.getCollection("sets3", String.class)); - System.out.println("[有值] sets3 EXISTS : " + source.exists("sets3")); - System.out.println("[有值] sets3-setvals2 EXISTSITEM : " + source.existsSetItem("sets3", String.class, "setvals2")); - System.out.println("[有值] sets3-setvals3 EXISTSITEM : " + source.existsSetItem("sets3", String.class, "setvals3")); - source.removeSetItem("sets3", String.class, "setvals1"); - System.out.println("[一值] sets3 VALUES : " + source.getCollection("sets3", String.class)); - System.out.println("sets3 大小 : " + source.getCollectionSize("sets3")); - System.out.println("all keys: " + source.queryKeys()); - System.out.println("key startkeys: " + source.queryKeysStartsWith("key")); - System.out.println("newnum 值 : " + source.incr("newnum")); - System.out.println("newnum 值 : " + source.decr("newnum")); - System.out.println("sets3&sets4: " + source.getStringCollectionMap(true, "sets3", "sets4")); - System.out.println("------------------------------------"); - source.set("myaddr", InetSocketAddress.class, addr); - System.out.println("myaddrstr: " + source.getString("myaddr")); - System.out.println("myaddr: " + source.get("myaddr", InetSocketAddress.class)); - source.remove("myaddrs"); - source.remove("myaddrs2"); - source.appendSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788)); - source.appendSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7799)); - System.out.println("myaddrs: " + source.getCollection("myaddrs", InetSocketAddress.class)); - source.removeSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788)); - System.out.println("myaddrs: " + source.getCollection("myaddrs", InetSocketAddress.class)); - source.appendSetItem("myaddrs2", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788)); - source.appendSetItem("myaddrs2", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7799)); - System.out.println("myaddrs&myaddrs2: " + source.getCollectionMap(true, InetSocketAddress.class, "myaddrs", "myaddrs2")); - System.out.println("------------------------------------"); - source.remove("myaddrs"); - Type mapType = new TypeToken>() { - }.getType(); - Map map = new HashMap<>(); - map.put("a", 1); - map.put("b", 2); - source.set("mapvals", mapType, map); - System.out.println("mapvals: " + source.get("mapvals", mapType)); - - source.remove("byteskey"); - source.setBytes("byteskey", new byte[]{1, 2, 3}); - System.out.println("byteskey 值 : " + Arrays.toString(source.getBytes("byteskey"))); - //h - source.remove("hmap"); - source.hincr("hmap", "key1"); - System.out.println("hmap.key1 值 : " + source.hgetLong("hmap", "key1", -1)); - source.hmset("hmap", "key2", "haha", "key3", 333); - source.hmset("hmap", "sm", (HashMap) Utility.ofMap("a", "aa", "b", "bb")); - System.out.println("hmap.sm 值 : " + source.hget("hmap", "sm", JsonConvert.TYPE_MAP_STRING_STRING)); - System.out.println("hmap.[key1,key2,key3] 值 : " + source.hmget("hmap", String.class, "key1", "key2", "key3")); - System.out.println("hmap.keys 四值 : " + source.hkeys("hmap")); - source.hremove("hmap", "key1", "key3"); - System.out.println("hmap.keys 两值 : " + source.hkeys("hmap")); - System.out.println("hmap.key2 值 : " + source.hgetString("hmap", "key2")); - System.out.println("hmap列表(2)大小 : " + source.hsize("hmap")); - - source.remove("hmaplong"); - source.hincr("hmaplong", "key1", 10); - source.hsetLong("hmaplong", "key2", 30); - System.out.println("hmaplong.所有两值 : " + source.hmap("hmaplong", long.class, 0, 10)); - - source.remove("hmapstr"); - source.hsetString("hmapstr", "key1", "str10"); - source.hsetString("hmapstr", "key2", null); - System.out.println("hmapstr.所有一值 : " + source.hmap("hmapstr", String.class, 0, 10)); - - source.remove("hmapstrmap"); - source.hset("hmapstrmap", "key1", JsonConvert.TYPE_MAP_STRING_STRING, (HashMap) Utility.ofMap("ks11", "vv11")); - source.hset("hmapstrmap", "key2", JsonConvert.TYPE_MAP_STRING_STRING, null); - System.out.println("hmapstrmap.无值 : " + source.hmap("hmapstrmap", JsonConvert.TYPE_MAP_STRING_STRING, 0, 10, "key2*")); - - source.remove("popset"); - source.appendStringSetItem("popset", "111"); - source.appendStringSetItem("popset", "222"); - source.appendStringSetItem("popset", "333"); - source.appendStringSetItem("popset", "444"); - source.appendStringSetItem("popset", "555"); - System.out.println("SPOP一个元素:" + source.spopStringSetItem("popset")); - System.out.println("SPOP两个元素:" + source.spopStringSetItem("popset", 2)); - System.out.println("SPOP五个元素:" + source.spopStringSetItem("popset", 5)); - source.appendLongSetItem("popset", 111); - source.appendLongSetItem("popset", 222); - source.appendLongSetItem("popset", 333); - source.appendLongSetItem("popset", 444); - source.appendLongSetItem("popset", 555); - System.out.println("SPOP一个元素:" + source.spopLongSetItem("popset")); - System.out.println("SPOP两个元素:" + source.spopLongSetItem("popset", 2)); - System.out.println("SPOP五个元素:" + source.spopLongSetItem("popset", 5)); - System.out.println("SPOP一个元素:" + source.spopLongSetItem("popset")); - - //清除 - int rs = source.remove("stritem1"); - System.out.println("删除stritem1个数: " + rs); - source.remove("popset"); - source.remove("stritem2"); - source.remove("intitem1"); - source.remove("intitem2"); - source.remove("keylong1"); - source.remove("keystr1"); - source.remove("mapvals"); - source.remove("myaddr"); - source.remove("myaddrs2"); - source.remove("newnum"); - source.remove("objitem1"); - source.remove("objitem2"); - source.remove("key1"); - source.remove("key2"); - source.remove("keys3"); - source.remove("sets3"); - source.remove("sets4"); - source.remove("myaddrs"); - source.remove("300"); - source.remove("stringmap"); - source.remove("hmap"); - source.remove("hmaplong"); - source.remove("hmapstr"); - source.remove("hmapstrmap"); - source.remove("byteskey"); - System.out.println("------------------------------------"); -// System.out.println("--------------测试大文本---------------"); -// HashMap bigmap = new HashMap<>(); -// StringBuilder sb = new StringBuilder(); -// sb.append("起始"); -// for (int i = 0; i < 1024 * 1024; i++) { -// sb.append("abcde"); -// } -// sb.append("结束"); -// bigmap.put("val", sb.toString()); -// System.out.println("文本长度: " + sb.length()); -// source.set("bigmap", JsonConvert.TYPE_MAP_STRING_STRING, bigmap); -// System.out.println("写入完成"); -// for (int i = 0; i < 1; i++) { -// HashMap fs = (HashMap) source.get("bigmap", JsonConvert.TYPE_MAP_STRING_STRING); -// System.out.println("内容长度: " + fs.get("val").length()); -// } - source.remove("bigmap"); - - } finally { - source.close(); - } - } - - @Override - public void close() throws Exception { //在 Application 关闭时调用 - destroy(null); - } - - @Override - public String resourceName() { - Resource res = this.getClass().getAnnotation(Resource.class); - return res == null ? "" : res.name(); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{addrs = " + this.nodeAddrs + ", db=" + this.db + "}"; - } - - @Override - public void destroy(AnyValue conf) { - if (transport != null) transport.close(); - } - - //--------------------- exists ------------------------------ - @Override - public CompletableFuture existsAsync(String key) { - return (CompletableFuture) send("EXISTS", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public boolean exists(String key) { - return existsAsync(key).join(); - } - - //--------------------- get ------------------------------ - @Override - @Deprecated - public CompletableFuture getAsync(String key) { - return (CompletableFuture) send("GET", CacheEntryType.OBJECT, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture getAsync(String key, Type type) { - return (CompletableFuture) send("GET", CacheEntryType.OBJECT, type, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture getStringAsync(String key) { - return (CompletableFuture) send("GET", CacheEntryType.STRING, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture getLongAsync(String key, long defValue) { - return ((CompletableFuture) send("GET", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8))).thenApplyAsync(v -> v == null ? defValue : v); - } - - @Override - @Deprecated - public V get(String key) { - return getAsync(key).join(); - } - - @Override - public T get(String key, final Type type) { - return (T) getAsync(key, type).join(); - } - - @Override - public String getString(String key) { - return getStringAsync(key).join(); - } - - @Override - public long getLong(String key, long defValue) { - return getLongAsync(key, defValue).join(); - } - - //--------------------- getAndRefresh ------------------------------ - @Override - @Deprecated - public CompletableFuture getAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getAsync(key)); - } - - @Override - public CompletableFuture getAndRefreshAsync(String key, int expireSeconds, final Type type) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getAsync(key, type)); - } - - @Override - @Deprecated - public V getAndRefresh(String key, final int expireSeconds) { - return getAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public T getAndRefresh(String key, final int expireSeconds, final Type type) { - return (T) getAndRefreshAsync(key, expireSeconds, type).join(); - } - - @Override - public CompletableFuture getStringAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getStringAsync(key)); - } - - @Override - public String getStringAndRefresh(String key, final int expireSeconds) { - return getStringAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public CompletableFuture getLongAndRefreshAsync(String key, int expireSeconds, long defValue) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getLongAsync(key, defValue)); - } - - @Override - public long getLongAndRefresh(String key, final int expireSeconds, long defValue) { - return getLongAndRefreshAsync(key, expireSeconds, defValue).join(); - } - - //--------------------- refresh ------------------------------ - @Override - public CompletableFuture refreshAsync(String key, int expireSeconds) { - return setExpireSecondsAsync(key, expireSeconds); - } - - @Override - public void refresh(String key, final int expireSeconds) { - setExpireSeconds(key, expireSeconds); - } - - //--------------------- set ------------------------------ - @Override - @Deprecated - public CompletableFuture setAsync(String key, V value) { - CacheEntryType cet = this.objValueType == String.class ? CacheEntryType.STRING : CacheEntryType.OBJECT; - return (CompletableFuture) send("SET", cet, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture setAsync(String key, Convert convert, T value) { - CacheEntryType cet = value instanceof CharSequence ? CacheEntryType.STRING : CacheEntryType.OBJECT; - return (CompletableFuture) send("SET", cet, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, convert, (Type) null, value)); - } - - @Override - public CompletableFuture setAsync(String key, final Type type, T value) { - CacheEntryType cet = type == String.class ? CacheEntryType.STRING : CacheEntryType.OBJECT; - return (CompletableFuture) send("SET", cet, type, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, (Convert) null, type, value)); - } - - @Override - public CompletableFuture setAsync(String key, Convert convert, final Type type, T value) { - CacheEntryType cet = type == String.class ? CacheEntryType.STRING : CacheEntryType.OBJECT; - return (CompletableFuture) send("SET", cet, type, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, convert, type, value)); - } - - @Override - @Deprecated - public void set(final String key, V value) { - setAsync(key, value).join(); - } - - @Override - public void set(final String key, final Convert convert, T value) { - setAsync(key, convert, value).join(); - } - - @Override - public void set(final String key, final Type type, T value) { - setAsync(key, type, value).join(); - } - - @Override - public void set(String key, final Convert convert, final Type type, T value) { - setAsync(key, convert, type, value).join(); - } - - @Override - public CompletableFuture setStringAsync(String key, String value) { - return (CompletableFuture) send("SET", CacheEntryType.STRING, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public void setString(String key, String value) { - setStringAsync(key, value).join(); - } - - @Override - public CompletableFuture setLongAsync(String key, long value) { - return (CompletableFuture) send("SET", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public void setLong(String key, long value) { - setLongAsync(key, value).join(); - } - - //--------------------- set ------------------------------ - @Override - @Deprecated - public CompletableFuture setAsync(int expireSeconds, String key, V value) { - return (CompletableFuture) setAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture setAsync(int expireSeconds, String key, Convert convert, T value) { - return (CompletableFuture) setAsync(key, convert, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture setAsync(int expireSeconds, String key, final Type type, T value) { - return (CompletableFuture) setAsync(key, type, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture setAsync(int expireSeconds, String key, Convert convert, final Type type, T value) { - return (CompletableFuture) setAsync(key, convert, type, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - @Deprecated - public void set(int expireSeconds, String key, V value) { - setAsync(expireSeconds, key, value).join(); - } - - @Override - public void set(int expireSeconds, String key, Convert convert, T value) { - setAsync(expireSeconds, key, convert, value).join(); - } - - @Override - public void set(int expireSeconds, String key, final Type type, T value) { - setAsync(expireSeconds, key, type, value).join(); - } - - @Override - public void set(int expireSeconds, String key, Convert convert, final Type type, T value) { - setAsync(expireSeconds, key, convert, type, value).join(); - } - - @Override - public CompletableFuture setStringAsync(int expireSeconds, String key, String value) { - return (CompletableFuture) setStringAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public void setString(int expireSeconds, String key, String value) { - setStringAsync(expireSeconds, key, value).join(); - } - - @Override - public CompletableFuture setLongAsync(int expireSeconds, String key, long value) { - return (CompletableFuture) setLongAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public void setLong(int expireSeconds, String key, long value) { - setLongAsync(expireSeconds, key, value).join(); - } - - //--------------------- setExpireSeconds ------------------------------ - @Override - public CompletableFuture setExpireSecondsAsync(String key, int expireSeconds) { - return (CompletableFuture) send("EXPIRE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public void setExpireSeconds(String key, int expireSeconds) { - setExpireSecondsAsync(key, expireSeconds).join(); - } - - //--------------------- remove ------------------------------ - @Override - public CompletableFuture removeAsync(String key) { - return (CompletableFuture) send("DEL", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public int remove(String key) { - return removeAsync(key).join(); - } - - //--------------------- incr ------------------------------ - @Override - public long incr(final String key) { - return incrAsync(key).join(); - } - - @Override - public CompletableFuture incrAsync(final String key) { - return (CompletableFuture) send("INCR", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public long incr(final String key, long num) { - return incrAsync(key, num).join(); - } - - @Override - public CompletableFuture incrAsync(final String key, long num) { - return (CompletableFuture) send("INCRBY", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)); - } - - //--------------------- decr ------------------------------ - @Override - public long decr(final String key) { - return decrAsync(key).join(); - } - - @Override - public CompletableFuture decrAsync(final String key) { - return (CompletableFuture) send("DECR", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public long decr(final String key, long num) { - return decrAsync(key, num).join(); - } - - @Override - public CompletableFuture decrAsync(final String key, long num) { - return (CompletableFuture) send("DECRBY", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public int hremove(final String key, String... fields) { - return hremoveAsync(key, fields).join(); - } - - @Override - public int hsize(final String key) { - return hsizeAsync(key).join(); - } - - @Override - public List hkeys(final String key) { - return hkeysAsync(key).join(); - } - - @Override - public long hincr(final String key, String field) { - return hincrAsync(key, field).join(); - } - - @Override - public long hincr(final String key, String field, long num) { - return hincrAsync(key, field, num).join(); - } - - @Override - public long hdecr(final String key, String field) { - return hdecrAsync(key, field).join(); - } - - @Override - public long hdecr(final String key, String field, long num) { - return hdecrAsync(key, field, num).join(); - } - - @Override - public boolean hexists(final String key, String field) { - return hexistsAsync(key, field).join(); - } - - @Override - public void hset(final String key, final String field, final Convert convert, final T value) { - hsetAsync(key, field, convert, value).join(); - } - - @Override - public void hset(final String key, final String field, final Type type, final T value) { - hsetAsync(key, field, type, value).join(); - } - - @Override - public void hset(final String key, final String field, final Convert convert, final Type type, final T value) { - hsetAsync(key, field, convert, type, value).join(); - } - - @Override - public void hsetString(final String key, final String field, final String value) { - hsetStringAsync(key, field, value).join(); - } - - @Override - public void hsetLong(final String key, final String field, final long value) { - hsetLongAsync(key, field, value).join(); - } - - @Override - public void hmset(final String key, final Serializable... values) { - hmsetAsync(key, values).join(); - } - - @Override - public List hmget(final String key, final Type type, final String... fields) { - return hmgetAsync(key, type, fields).join(); - } - - @Override - public Map hmap(final String key, final Type type, int offset, int limit, String pattern) { - return (Map) hmapAsync(key, type, offset, limit, pattern).join(); - } - - @Override - public Map hmap(final String key, final Type type, int offset, int limit) { - return (Map) hmapAsync(key, type, offset, limit).join(); - } - - @Override - public T hget(final String key, final String field, final Type type) { - return (T) hgetAsync(key, field, type).join(); - } - - @Override - public String hgetString(final String key, final String field) { - return hgetStringAsync(key, field).join(); - } - - @Override - public long hgetLong(final String key, final String field, long defValue) { - return hgetLongAsync(key, field, defValue).join(); - } - - @Override - public CompletableFuture hremoveAsync(final String key, String... fields) { - byte[][] bs = new byte[fields.length + 1][]; - bs[0] = key.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < fields.length; i++) { - bs[i + 1] = fields[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("HDEL", CacheEntryType.MAP, (Type) null, key, bs); - } - - @Override - public CompletableFuture hsizeAsync(final String key) { - return (CompletableFuture) send("HLEN", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> hkeysAsync(final String key) { - return (CompletableFuture) send("HKEYS", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hincrAsync(final String key, String field) { - return hincrAsync(key, field, 1); - } - - @Override - public CompletableFuture hincrAsync(final String key, String field, long num) { - return (CompletableFuture) send("HINCRBY", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hdecrAsync(final String key, String field) { - return hincrAsync(key, field, -1); - } - - @Override - public CompletableFuture hdecrAsync(final String key, String field, long num) { - return hincrAsync(key, field, -num); - } - - @Override - public CompletableFuture hexistsAsync(final String key, String field) { - return (CompletableFuture) send("HEXISTS", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Convert convert, final T value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.MAP, convert, null, value)); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Type type, final T value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, type, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.MAP, null, type, value)); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Convert convert, final Type type, final T value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, type, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.MAP, convert, type, value)); - } - - @Override - public CompletableFuture hsetStringAsync(final String key, final String field, final String value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, null, null, value)); - } - - @Override - public CompletableFuture hsetLongAsync(final String key, final String field, final long value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, null, null, value)); - } - - @Override - public CompletableFuture hmsetAsync(final String key, final Serializable... values) { - byte[][] bs = new byte[values.length + 1][]; - bs[0] = key.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < values.length; i += 2) { - bs[i + 1] = String.valueOf(values[i]).getBytes(StandardCharsets.UTF_8); - bs[i + 2] = formatValue(CacheEntryType.MAP, null, null, values[i + 1]); - } - return (CompletableFuture) send("HMSET", CacheEntryType.MAP, (Type) null, key, bs); - } - - @Override - public CompletableFuture> hmgetAsync(final String key, final Type type, final String... fields) { - byte[][] bs = new byte[fields.length + 1][]; - bs[0] = key.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < fields.length; i++) { - bs[i + 1] = fields[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("HMGET", CacheEntryType.MAP, type, key, bs); - } - - @Override - public CompletableFuture> hmapAsync(final String key, final Type type, int offset, int limit) { - return hmapAsync(key, type, offset, limit, null); - } - - @Override - public CompletableFuture> hmapAsync(final String key, final Type type, int offset, int limit, String pattern) { - byte[][] bs = new byte[pattern == null || pattern.isEmpty() ? 4 : 6][limit]; - int index = -1; - bs[++index] = key.getBytes(StandardCharsets.UTF_8); - bs[++index] = String.valueOf(offset).getBytes(StandardCharsets.UTF_8); - if (pattern != null && !pattern.isEmpty()) { - bs[++index] = "MATCH".getBytes(StandardCharsets.UTF_8); - bs[++index] = pattern.getBytes(StandardCharsets.UTF_8); - } - bs[++index] = "COUNT".getBytes(StandardCharsets.UTF_8); - bs[++index] = String.valueOf(limit).getBytes(StandardCharsets.UTF_8); - return (CompletableFuture) send("HSCAN", CacheEntryType.MAP, type, key, bs); - } - - @Override - public CompletableFuture hgetAsync(final String key, final String field, final Type type) { - return (CompletableFuture) send("HGET", CacheEntryType.OBJECT, type, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hgetStringAsync(final String key, final String field) { - return (CompletableFuture) send("HGET", CacheEntryType.STRING, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hgetLongAsync(final String key, final String field, long defValue) { - return (CompletableFuture) send("HGET", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)).thenApplyAsync(v -> v == null ? defValue : v); - } - - //--------------------- collection ------------------------------ - @Override - public CompletableFuture getCollectionSizeAsync(String key) { - return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(0); - String rs = new String((byte[]) t); - if (rs.contains("zset")) { // ziplist - return send("ZCARD", null, int.class, key, key.getBytes(StandardCharsets.UTF_8)); - } else if (rs.contains("list")) { //list - return send("LLEN", null, int.class, key, key.getBytes(StandardCharsets.UTF_8)); - } else if (rs.contains("hash")) { - return send("HLEN", null, int.class, key, key.getBytes(StandardCharsets.UTF_8)); - } else { - return send("SCARD", null, int.class, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public int getCollectionSize(String key) { - return getCollectionSizeAsync(key).join(); - } - - @Override - @Deprecated - public CompletableFuture> getCollectionAsync(String key) { - return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(null); - String str = new String((byte[]) t); - if (str.contains("list")) { //list - return send("LRANGE", CacheEntryType.OBJECT, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}); - } else if (str.contains("none")) { - return CompletableFuture.completedFuture(new ArrayList<>()); - } else { - return send("SMEMBERS", CacheEntryType.OBJECT, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public CompletableFuture> getCollectionAsync(String key, final Type componentType) { - return (CompletableFuture) send("TYPE", null, componentType, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(null); - if (new String((byte[]) t).contains("list")) { //list - return send("LRANGE", CacheEntryType.OBJECT, componentType, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}); - } else { - return send("SMEMBERS", CacheEntryType.OBJECT, componentType, true, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public CompletableFuture> getLongMapAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.LONG, null, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - Map map = new LinkedHashMap<>(); - for (int i = 0; i < keys.length; i++) { - Object obj = list.get(i); - if (obj != null) map.put(keys[i], list.get(i)); - } - return map; - }); - } - - @Override - public CompletableFuture getLongArrayAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.LONG, null, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - Long[] rs = new Long[keys.length]; - for (int i = 0; i < keys.length; i++) { - Number obj = (Number) list.get(i); - rs[i] = obj == null ? null : obj.longValue(); - } - return rs; - }); - } - - @Override - public CompletableFuture getStringArrayAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.STRING, null, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - String[] rs = new String[keys.length]; - for (int i = 0; i < keys.length; i++) { - Object obj = list.get(i); - rs[i] = obj == null ? null : obj.toString(); - } - return rs; - }); - } - - @Override - public CompletableFuture> getStringMapAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.STRING, null, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - Map map = new LinkedHashMap<>(); - for (int i = 0; i < keys.length; i++) { - Object obj = list.get(i); - if (obj != null) map.put(keys[i], list.get(i)); - } - return map; - }); - } - - @Override - public CompletableFuture> getMapAsync(final Type componentType, String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.OBJECT, componentType, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - Map map = new LinkedHashMap<>(); - for (int i = 0; i < keys.length; i++) { - Object obj = list.get(i); - if (obj != null) map.put(keys[i], list.get(i)); - } - return map; - }); - } - - @Override - public CompletableFuture>> getCollectionMapAsync(final boolean set, final Type componentType, final String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new HashMap<>(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - if (!set) { //list - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("LRANGE", CacheEntryType.OBJECT, componentType, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } else { - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("SMEMBERS", CacheEntryType.OBJECT, componentType, true, key, key.getBytes(StandardCharsets.UTF_8)).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - @Deprecated - public Collection getCollection(String key) { - return getCollectionAsync(key).join(); - } - - @Override - public Collection getCollection(String key, final Type componentType) { - return (Collection) getCollectionAsync(key, componentType).join(); - } - - @Override - public Map getLongMap(final String... keys) { - return getLongMapAsync(keys).join(); - } - - @Override - public Long[] getLongArray(final String... keys) { - return getLongArrayAsync(keys).join(); - } - - @Override - public Map getStringMap(final String... keys) { - return getStringMapAsync(keys).join(); - } - - @Override - public String[] getStringArray(final String... keys) { - return getStringArrayAsync(keys).join(); - } - - @Override - public Map getMap(final Type componentType, final String... keys) { - return (Map) getMapAsync(componentType, keys).join(); - } - - @Override - public Map> getCollectionMap(final boolean set, final Type componentType, String... keys) { - return (Map) getCollectionMapAsync(set, componentType, keys).join(); - } - - @Override - public CompletableFuture> getStringCollectionAsync(String key) { - return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(null); - if (new String((byte[]) t).contains("list")) { //list - return send("LRANGE", CacheEntryType.STRING, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}); - } else { - return send("SMEMBERS", CacheEntryType.STRING, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public CompletableFuture>> getStringCollectionMapAsync(final boolean set, String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new HashMap<>(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - if (!set) { //list - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("LRANGE", CacheEntryType.STRING, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } else { - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("SMEMBERS", CacheEntryType.STRING, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - public Collection getStringCollection(String key) { - return getStringCollectionAsync(key).join(); - } - - @Override - public Map> getStringCollectionMap(final boolean set, String... keys) { - return getStringCollectionMapAsync(set, keys).join(); - } - - @Override - public CompletableFuture> getLongCollectionAsync(String key) { - return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(null); - if (new String((byte[]) t).contains("list")) { //list - return send("LRANGE", CacheEntryType.LONG, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}); - } else { - return send("SMEMBERS", CacheEntryType.LONG, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public CompletableFuture>> getLongCollectionMapAsync(final boolean set, String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new HashMap<>(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - if (!set) { //list - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("LRANGE", CacheEntryType.LONG, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } else { - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("SMEMBERS", CacheEntryType.LONG, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - public Collection getLongCollection(String key) { - return getLongCollectionAsync(key).join(); - } - - @Override - public Map> getLongCollectionMap(final boolean set, String... keys) { - return getLongCollectionMapAsync(set, keys).join(); - } - - //--------------------- getCollectionAndRefresh ------------------------------ - @Override - @Deprecated - public CompletableFuture> getCollectionAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getCollectionAsync(key)); - } - - @Override - public CompletableFuture> getCollectionAndRefreshAsync(String key, int expireSeconds, final Type componentType) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getCollectionAsync(key, componentType)); - } - - @Override - @Deprecated - public Collection getCollectionAndRefresh(String key, final int expireSeconds) { - return getCollectionAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public Collection getCollectionAndRefresh(String key, final int expireSeconds, final Type componentType) { - return (Collection) getCollectionAndRefreshAsync(key, expireSeconds, componentType).join(); - } - - @Override - public CompletableFuture> getStringCollectionAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getStringCollectionAsync(key)); - } - - @Override - public Collection getStringCollectionAndRefresh(String key, final int expireSeconds) { - return getStringCollectionAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public CompletableFuture> getLongCollectionAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getLongCollectionAsync(key)); - } - - @Override - public Collection getLongCollectionAndRefresh(String key, final int expireSeconds) { - return getLongCollectionAndRefreshAsync(key, expireSeconds).join(); - } - - //--------------------- existsItem ------------------------------ - @Override - @Deprecated - public boolean existsSetItem(String key, V value) { - return existsSetItemAsync(key, value).join(); - } - - @Override - public boolean existsSetItem(String key, final Type componentType, T value) { - return existsSetItemAsync(key, componentType, value).join(); - } - - @Override - @Deprecated - public CompletableFuture existsSetItemAsync(String key, V value) { - return (CompletableFuture) send("SISMEMBER", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture existsSetItemAsync(String key, final Type componentType, T value) { - return (CompletableFuture) send("SISMEMBER", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - public boolean existsStringSetItem(String key, String value) { - return existsStringSetItemAsync(key, value).join(); - } - - @Override - public CompletableFuture existsStringSetItemAsync(String key, String value) { - return (CompletableFuture) send("SISMEMBER", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public boolean existsLongSetItem(String key, long value) { - return existsLongSetItemAsync(key, value).join(); - } - - @Override - public CompletableFuture existsLongSetItemAsync(String key, long value) { - return (CompletableFuture) send("SISMEMBER", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - //--------------------- appendListItem ------------------------------ - @Override - @Deprecated - public CompletableFuture appendListItemAsync(String key, V value) { - return (CompletableFuture) send("RPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture appendListItemAsync(String key, final Type componentType, T value) { - return (CompletableFuture) send("RPUSH", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - @Deprecated - public void appendListItem(String key, V value) { - appendListItemAsync(key, value).join(); - } - - @Override - public void appendListItem(String key, final Type componentType, T value) { - appendListItemAsync(key, componentType, value).join(); - } - - @Override - public CompletableFuture appendStringListItemAsync(String key, String value) { - return (CompletableFuture) send("RPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public void appendStringListItem(String key, String value) { - appendStringListItemAsync(key, value).join(); - } - - @Override - public CompletableFuture appendLongListItemAsync(String key, long value) { - return (CompletableFuture) send("RPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public void appendLongListItem(String key, long value) { - appendLongListItemAsync(key, value).join(); - } - - //--------------------- removeListItem ------------------------------ - @Override - @Deprecated - public CompletableFuture removeListItemAsync(String key, V value) { - return (CompletableFuture) send("LREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture removeListItemAsync(String key, final Type componentType, T value) { - return (CompletableFuture) send("LREM", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - @Deprecated - public int removeListItem(String key, V value) { - return removeListItemAsync(key, value).join(); - } - - @Override - public int removeListItem(String key, final Type componentType, T value) { - return removeListItemAsync(key, componentType, value).join(); - } - - @Override - public CompletableFuture removeStringListItemAsync(String key, String value) { - return (CompletableFuture) send("LREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public int removeStringListItem(String key, String value) { - return removeStringListItemAsync(key, value).join(); - } - - @Override - public CompletableFuture removeLongListItemAsync(String key, long value) { - return (CompletableFuture) send("LREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public int removeLongListItem(String key, long value) { - return removeLongListItemAsync(key, value).join(); - } - - //--------------------- appendSetItem ------------------------------ - @Override - @Deprecated - public CompletableFuture appendSetItemAsync(String key, V value) { - return (CompletableFuture) send("SADD", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture appendSetItemAsync(String key, Type componentType, T value) { - return (CompletableFuture) send("SADD", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - public CompletableFuture spopSetItemAsync(String key, Type componentType) { - return (CompletableFuture) send("SPOP", CacheEntryType.OBJECT, componentType, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> spopSetItemAsync(String key, int count, Type componentType) { - return (CompletableFuture) send("SPOP", CacheEntryType.OBJECT, componentType, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture spopStringSetItemAsync(String key) { - return (CompletableFuture) send("SPOP", CacheEntryType.STRING, String.class, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> spopStringSetItemAsync(String key, int count) { - return (CompletableFuture) send("SPOP", CacheEntryType.STRING, String.class, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture spopLongSetItemAsync(String key) { - return (CompletableFuture) send("SPOP", CacheEntryType.LONG, long.class, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> spopLongSetItemAsync(String key, int count) { - return (CompletableFuture) send("SPOP", CacheEntryType.LONG, long.class, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8)); - } - - @Override - @Deprecated - public void appendSetItem(String key, V value) { - appendSetItemAsync(key, value).join(); - } - - @Override - public void appendSetItem(String key, final Type componentType, T value) { - appendSetItemAsync(key, componentType, value).join(); - } - - @Override - public T spopSetItem(String key, final Type componentType) { - return (T) spopSetItemAsync(key, componentType).join(); - } - - @Override - public List spopSetItem(String key, int count, final Type componentType) { - return (List) spopSetItemAsync(key, count, componentType).join(); - } - - @Override - public String spopStringSetItem(String key) { - return spopStringSetItemAsync(key).join(); - } - - @Override - public List spopStringSetItem(String key, int count) { - return spopStringSetItemAsync(key, count).join(); - } - - @Override - public Long spopLongSetItem(String key) { - return spopLongSetItemAsync(key).join(); - } - - @Override - public List spopLongSetItem(String key, int count) { - return spopLongSetItemAsync(key, count).join(); - } - - @Override - public CompletableFuture appendStringSetItemAsync(String key, String value) { - return (CompletableFuture) send("SADD", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public void appendStringSetItem(String key, String value) { - appendStringSetItemAsync(key, value).join(); - } - - @Override - public CompletableFuture appendLongSetItemAsync(String key, long value) { - return (CompletableFuture) send("SADD", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public void appendLongSetItem(String key, long value) { - appendLongSetItemAsync(key, value).join(); - } - - //--------------------- removeSetItem ------------------------------ - @Override - @Deprecated - public CompletableFuture removeSetItemAsync(String key, V value) { - return (CompletableFuture) send("SREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture removeSetItemAsync(String key, final Type componentType, T value) { - return (CompletableFuture) send("SREM", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - @Deprecated - public int removeSetItem(String key, V value) { - return removeSetItemAsync(key, value).join(); - } - - @Override - public int removeSetItem(String key, final Type componentType, T value) { - return removeSetItemAsync(key, componentType, value).join(); - } - - @Override - public CompletableFuture removeStringSetItemAsync(String key, String value) { - return (CompletableFuture) send("SREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public int removeStringSetItem(String key, String value) { - return removeStringSetItemAsync(key, value).join(); - } - - @Override - public CompletableFuture removeLongSetItemAsync(String key, long value) { - return (CompletableFuture) send("SREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public int removeLongSetItem(String key, long value) { - return removeLongSetItemAsync(key, value).join(); - } - - //--------------------- queryKeys ------------------------------ - @Override - public List queryKeys() { - return queryKeysAsync().join(); - } - - @Override - public List queryKeysStartsWith(String startsWith) { - return queryKeysStartsWithAsync(startsWith).join(); - } - - @Override - public List queryKeysEndsWith(String endsWith) { - return queryKeysEndsWithAsync(endsWith).join(); - } - - @Override - public byte[] getBytes(final String key) { - return getBytesAsync(key).join(); - } - - @Override - public byte[] getBytesAndRefresh(final String key, final int expireSeconds) { - return getBytesAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public void setBytes(final String key, final byte[] value) { - setBytesAsync(key, value).join(); - } - - @Override - public void setBytes(final int expireSeconds, final String key, final byte[] value) { - setBytesAsync(expireSeconds, key, value).join(); - } - - @Override - public void setBytes(final String key, final Convert convert, final Type type, final T value) { - setBytesAsync(key, convert, type, value).join(); - } - - @Override - public void setBytes(final int expireSeconds, final String key, final Convert convert, final Type type, final T value) { - setBytesAsync(expireSeconds, key, convert, type, value).join(); - } - - @Override - public CompletableFuture getBytesAsync(final String key) { - return (CompletableFuture) send("GET", CacheEntryType.BYTES, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture getBytesAndRefreshAsync(final String key, final int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getBytesAsync(key)); - } - - @Override - public CompletableFuture setBytesAsync(final String key, final byte[] value) { - return (CompletableFuture) send("SET", CacheEntryType.BYTES, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), value); - - } - - @Override - public CompletableFuture setBytesAsync(final int expireSeconds, final String key, final byte[] value) { - return (CompletableFuture) setBytesAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture setBytesAsync(final String key, final Convert convert, final Type type, final T value) { - return (CompletableFuture) send("SET", CacheEntryType.BYTES, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), convert.convertToBytes(type, value)); - } - - @Override - public CompletableFuture setBytesAsync(final int expireSeconds, final String key, final Convert convert, final Type type, final T value) { - return (CompletableFuture) setBytesAsync(key, convert.convertToBytes(type, value)).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture> queryKeysAsync() { - return (CompletableFuture) send("KEYS", null, (Type) null, "*", new byte[]{(byte) '*'}); - } - - @Override - public CompletableFuture> queryKeysStartsWithAsync(String startsWith) { - if (startsWith == null) return queryKeysAsync(); - String key = startsWith + "*"; - return (CompletableFuture) send("KEYS", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> queryKeysEndsWithAsync(String endsWith) { - if (endsWith == null) return queryKeysAsync(); - String key = "*" + endsWith; - return (CompletableFuture) send("KEYS", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - //--------------------- getKeySize ------------------------------ - @Override - public int getKeySize() { - return getKeySizeAsync().join(); - } - - @Override - public CompletableFuture getKeySizeAsync() { - return (CompletableFuture) send("DBSIZE", null, (Type) null, null); - } - - //--------------------- queryList ------------------------------ - @Override - public List> queryList() { - return queryListAsync().join(); - } - - @Override - public CompletableFuture>> queryListAsync() { - return CompletableFuture.completedFuture(new ArrayList<>()); //不返回数据 - } - - //--------------------- send ------------------------------ - private byte[] formatValue(CacheEntryType cacheType, Convert convert0, Type resultType, Object value) { - if (value == null) return "null".getBytes(StandardCharsets.UTF_8); - if (value instanceof byte[]) return (byte[]) value; - if (convert0 == null) convert0 = convert; - if (cacheType == CacheEntryType.MAP) { - if ((value instanceof CharSequence) || (value instanceof Number)) { - return String.valueOf(value).getBytes(StandardCharsets.UTF_8); - } - if (objValueType == String.class && !(value instanceof CharSequence)) resultType = value.getClass(); - return convert0.convertToBytes(resultType == null ? objValueType : resultType, value); - } - if (value instanceof Number || cacheType == CacheEntryType.LONG || cacheType == CacheEntryType.ATOMIC || value.getClass() == String.class) - return String.valueOf(value).getBytes(StandardCharsets.UTF_8); - if (cacheType == CacheEntryType.STRING) return convert0.convertToBytes(String.class, value); - return convert0.convertToBytes(resultType == null ? objValueType : resultType, value); - } - - protected CompletableFuture send(final String command, final CacheEntryType cacheType, final Type resultType, final String key, final byte[]... args) { - return send(command, cacheType, resultType, false, key, args); - } - - protected CompletableFuture send(final String command, final CacheEntryType cacheType, final Type resultType, final boolean set, final String key, final byte[]... args) { - return send(null, command, cacheType, resultType, set, key, args); - } - - private CompletableFuture send(final CompletionHandler callback, final String command, final CacheEntryType cacheType, final Type resultType, final boolean set, final String key, final byte[]... args) { - final ByteArray writer = new ByteArray(); - writer.put(ASTERISK_BYTE); - writer.put(String.valueOf(args.length + 1).getBytes(StandardCharsets.UTF_8)); - writer.put((byte) '\r', (byte) '\n'); - writer.put(DOLLAR_BYTE); - writer.put(String.valueOf(command.length()).getBytes(StandardCharsets.UTF_8)); - writer.put((byte) '\r', (byte) '\n'); - writer.put(command.getBytes(StandardCharsets.UTF_8)); - writer.put((byte) '\r', (byte) '\n'); - - for (final byte[] arg : args) { - writer.put(DOLLAR_BYTE); - writer.put(String.valueOf(arg.length).getBytes(StandardCharsets.UTF_8)); - writer.put((byte) '\r', (byte) '\n'); - writer.put(arg); - writer.put((byte) '\r', (byte) '\n'); - } - - final CompletableFuture future = callback == null ? new CompletableFuture<>() : null; - CompletableFuture connFuture = this.transport.pollConnection(null); - if (passwords != null) { - connFuture = connFuture.thenCompose(conn -> { - if (conn.getSubobject() != null) return CompletableFuture.completedFuture(conn); - byte[] password = passwords.get(conn.getRemoteAddress()); - if (password == null) return CompletableFuture.completedFuture(conn); - CompletableFuture rs = auth(conn, password, command); - if (db > 0) { - rs = rs.thenCompose(conn2 -> { - if (conn2.getSubobject() != null) return CompletableFuture.completedFuture(conn2); - return selectdb(conn2, db, command); - }); - } - return rs; - }); - } else if (db > 0) { - connFuture = connFuture.thenCompose(conn2 -> { - if (conn2.getSubobject() != null) return CompletableFuture.completedFuture(conn2); - return selectdb(conn2, db, command); - }); - } - connFuture.whenComplete((conn, ex) -> { - if (ex != null) { - if (future == null) { - callback.failed(ex, null); - } else { - future.completeExceptionally(ex); - } - return; - } - conn.write(writer, new CompletionHandler() { - @Override - public void completed(Integer result, Void attachment0) { - try { - //----------------------- 读取返回结果 ------------------------------------- - conn.read(new ReplyCompletionHandler(conn) { - @Override - public void completed(Integer result, ByteBuffer buffer) { - buffer.flip(); - try { - final byte sign = buffer.get(); - if (sign == PLUS_BYTE) { // + - byte[] bs = readBytes(buffer); - if (future == null) { - transport.offerConnection(false, conn); //必须在complete之前,防止并发是conn还没回收完毕 - callback.completed(null, key); - } else { - transport.offerConnection(false, conn); - future.complete(("SET".equals(command) || "HSET".equals(command)) ? null : bs); - } - } else if (sign == MINUS_BYTE) { // - - String bs = readString(buffer); - if (future == null) { - transport.offerConnection(false, conn); - callback.failed(new RuntimeException(bs), key); - } else { - transport.offerConnection(false, conn); - future.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } - } else if (sign == COLON_BYTE) { // : - long rs = readLong(buffer); - if (future == null) { - if (command.startsWith("INCR") || command.startsWith("DECR") || command.startsWith("HINCR")) { - transport.offerConnection(false, conn); - callback.completed(rs, key); - } else { - transport.offerConnection(false, conn); - callback.completed((command.endsWith("EXISTS") || "SISMEMBER".equals(command)) ? (rs > 0) : (("LLEN".equals(command) || "SCARD".equals(command) || "SREM".equals(command) || "LREM".equals(command) || "DEL".equals(command) || "HDEL".equals(command) || "HLEN".equals(command) || "DBSIZE".equals(command)) ? (int) rs : null), key); - } - } else { - if (command.startsWith("INCR") || command.startsWith("DECR") || command.startsWith("HINCR") || command.startsWith("HGET")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else if (command.equals("ZRANK") || command.equals("ZREVRANK")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else if (command.equals("GETBIT")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else if (command.equals("TTL") || command.equals("PTTL")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else if (command.equals("SETNX")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else { - transport.offerConnection(false, conn); - future.complete((command.endsWith("EXISTS") || "SISMEMBER".equals(command)) ? (rs > 0) : (("LLEN".equals(command) || "SCARD".equals(command) || "SREM".equals(command) || "LREM".equals(command) || "DEL".equals(command) || "HDEL".equals(command) || "HLEN".equals(command) || "DBSIZE".equals(command) || "ZCARD".equals(command) || "EVAL".equals(command)) ? (int) rs : null)); - } - } - } else if (sign == DOLLAR_BYTE) { // $ - long val = readLong(buffer); - byte[] rs = val <= 0 ? null : readBytes(buffer); - Type ct = cacheType == CacheEntryType.LONG ? long.class : (cacheType == CacheEntryType.STRING ? String.class : (resultType == null ? objValueType : resultType)); - if (future == null) { - transport.offerConnection(false, conn); - callback.completed((("SPOP".equals(command) || command.endsWith("GET") || rs == null) ? (ct == String.class && rs != null ? new String(rs, StandardCharsets.UTF_8) : convert.convertFrom(ct, new String(rs, StandardCharsets.UTF_8))) : null), key); - } else { - transport.offerConnection(false, conn); - if ("ZSCORE".equals(command)) { - future.complete(ct == String.class && rs != null ? new String(rs, StandardCharsets.UTF_8) : convert.convertFrom(ct, rs == null ? null : new String(rs, StandardCharsets.UTF_8))); - } else if (command.equals("HINCRBYFLOAT")) { - future.complete(new String(rs, StandardCharsets.UTF_8)); - } else { - future.complete("SPOP".equals(command) || command.endsWith("GET") || command.endsWith("ZINCRBY") ? (ct == String.class && rs != null ? new String(rs, StandardCharsets.UTF_8) : convert.convertFrom(ct, rs == null ? null : new String(rs, StandardCharsets.UTF_8))) : rs); - } - } - } else if (sign == ASTERISK_BYTE) { // * - final int len = readInt(buffer); - if (len < 0) { - if (future == null) { - transport.offerConnection(false, conn); - callback.completed(null, key); - } else { - transport.offerConnection(false, conn); - future.complete((byte[]) null); - } - } else { - Object rsobj; - if (command.endsWith("SCAN")) { - LinkedHashMap rs = new LinkedHashMap(); - rsobj = rs; - for (int i = 0; i < len; i++) { - int l = readInt(buffer); - if (l > 0) { - readBytes(buffer); - } else { - while (buffer.hasRemaining()) { - readBytes(buffer); - String field = new String(readBytes(buffer), StandardCharsets.UTF_8); - String value = null; - if (readInt(buffer) > 0) { - value = new String(readBytes(buffer), StandardCharsets.UTF_8); - } - Type ct = cacheType == CacheEntryType.LONG ? long.class : (cacheType == CacheEntryType.STRING ? String.class : (resultType == null ? objValueType : resultType)); - try { - rs.put(field, value == null ? null : (ct == String.class ? value : convert.convertFrom(ct, value))); - } catch (RuntimeException e) { - buffer.flip(); - byte[] bsss = new byte[buffer.remaining()]; - buffer.get(bsss); - logger.log(Level.SEVERE, "异常: " + new String(bsss)); - throw e; - } - } - } - } - } else { - Collection rs = set ? new HashSet() : new ArrayList(); - rsobj = rs; - boolean keys = "KEYS".equals(command) || "HKEYS".equals(command); - boolean mget = !keys && ("MGET".equals(command) || "HMGET".equals(command)); - boolean zsetscore = !keys && ("ZREVRANGE".equals(command) || "ZRANGE".equals(command)); - boolean hgetall = !keys && "HGETALL".equals(command); - boolean lpop = !keys && "BRPOP".equals(command); - Type ct = cacheType == CacheEntryType.LONG ? long.class : (cacheType == CacheEntryType.STRING ? String.class : (resultType == null ? objValueType : resultType)); - for (int i = 0; i < len; i++) { - int l = readInt(buffer); - if (l > 0) { - // 1、zsetscore 查询 偶数元素统一返回 string 方法内自定义转换 - // 2、hgetall 基数元素返回 string - if ((zsetscore && rs.size() % 2 == 1) || (hgetall && rs.size() % 2 == 0)) { - rs.add(readString(buffer)); - } else if (lpop && i == 1) { - rsobj = convert.convertFrom(ct, new String(readBytes(buffer), StandardCharsets.UTF_8)); - } else { - rs.add(keys ? new String(readBytes(buffer), StandardCharsets.UTF_8) : (ct == String.class ? new String(readBytes(buffer), StandardCharsets.UTF_8) : convert.convertFrom(ct, new String(readBytes(buffer), StandardCharsets.UTF_8)))); - } - } else if (mget) { - rs.add(null); - } - } - } - if (future == null) { - transport.offerConnection(false, conn); - callback.completed(rsobj, key); - } else { - transport.offerConnection(false, conn); - future.complete((Serializable) rsobj); - } - } - } else { - String exstr = "Unknown reply: " + (char) sign; - if (future == null) { - transport.offerConnection(false, conn); - callback.failed(new RuntimeException(exstr), key); - } else { - transport.offerConnection(false, conn); - future.completeExceptionally(new RuntimeException(exstr)); - } - } - } catch (Exception e) { - failed(e, buffer); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer attachment) { - conn.offerBuffer(attachment); - transport.offerConnection(true, conn); - if (future == null) { - callback.failed(exc, attachment0); - } else { - future.completeExceptionally(exc); - } - } - - }); - } catch (Exception e) { - failed(e, attachment0); - } - } - - @Override - public void failed(Throwable exc, Void attachment0) { - transport.offerConnection(true, conn); - if (future == null) { - callback.failed(exc, attachment0); - } else { - future.completeExceptionally(exc); - } - } - }); - }); - return future; //.orTimeout(3, TimeUnit.SECONDS) JDK9以上才支持 - } - - private CompletableFuture selectdb(final AsyncConnection conn, final int db, final String command) { - final CompletableFuture rsfuture = new CompletableFuture(); - try { - final ByteArray dbwriter = new ByteArray(); - dbwriter.put(ASTERISK_BYTE); - dbwriter.put((byte) '2'); - dbwriter.put((byte) '\r', (byte) '\n'); - dbwriter.put(DOLLAR_BYTE); - dbwriter.put((byte) '6'); - dbwriter.put((byte) '\r', (byte) '\n'); - dbwriter.put("SELECT".getBytes(StandardCharsets.UTF_8)); - dbwriter.put((byte) '\r', (byte) '\n'); - - dbwriter.put(DOLLAR_BYTE); - dbwriter.put(String.valueOf(String.valueOf(db).length()).getBytes(StandardCharsets.UTF_8)); - dbwriter.put((byte) '\r', (byte) '\n'); - dbwriter.put(String.valueOf(db).getBytes(StandardCharsets.UTF_8)); - dbwriter.put((byte) '\r', (byte) '\n'); - - conn.write(dbwriter, new CompletionHandler() { - @Override - public void completed(Integer result, Void attachments) { - try { - //----------------------- 读取返回结果 ------------------------------------- - conn.read(new ReplyCompletionHandler(conn) { - @Override - public void completed(Integer result, ByteBuffer buffer) { - buffer.flip(); - try { - final byte sign = buffer.get(); - if (sign == PLUS_BYTE) { // + - byte[] bs = readBytes(buffer); - if ("OK".equalsIgnoreCase(new String(bs))) { - conn.setSubobject("authed+db"); - rsfuture.complete(conn); - } else { - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } - } else if (sign == MINUS_BYTE) { // - 异常 - String bs = readString(buffer); - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } else { - String exstr = "Unknown reply: " + (char) sign; - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException(exstr)); - } - } catch (Exception e) { - failed(e, buffer); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer buffer) { - conn.offerBuffer(buffer); - transport.offerConnection(true, conn); - rsfuture.completeExceptionally(exc); - } - - }); - } catch (Exception e) { - failed(e, attachments); - } - } - - @Override - public void failed(Throwable exc, Void attachments) { - transport.offerConnection(true, conn); - rsfuture.completeExceptionally(exc); - } - }); - } catch (Exception e) { - rsfuture.completeExceptionally(e); - } - return rsfuture; - } - - private CompletableFuture auth(final AsyncConnection conn, final byte[] password, final String command) { - final CompletableFuture rsfuture = new CompletableFuture(); - try { - final ByteArray authwriter = new ByteArray(); - authwriter.put(ASTERISK_BYTE); - authwriter.put((byte) '2'); - authwriter.put((byte) '\r', (byte) '\n'); - authwriter.put(DOLLAR_BYTE); - authwriter.put((byte) '4'); - authwriter.put((byte) '\r', (byte) '\n'); - authwriter.put("AUTH".getBytes(StandardCharsets.UTF_8)); - authwriter.put((byte) '\r', (byte) '\n'); - - authwriter.put(DOLLAR_BYTE); - authwriter.put(String.valueOf(password.length).getBytes(StandardCharsets.UTF_8)); - authwriter.put((byte) '\r', (byte) '\n'); - authwriter.put(password); - authwriter.put((byte) '\r', (byte) '\n'); - - conn.write(authwriter, new CompletionHandler() { - @Override - public void completed(Integer result, Void attachments) { - try { - //----------------------- 读取返回结果 ------------------------------------- - conn.read(new ReplyCompletionHandler(conn) { - @Override - public void completed(Integer result, ByteBuffer buffer) { - buffer.flip(); - try { - final byte sign = buffer.get(); - if (sign == PLUS_BYTE) { // + - byte[] bs = readBytes(buffer); - if ("OK".equalsIgnoreCase(new String(bs))) { - conn.setSubobject("authed"); - rsfuture.complete(conn); - } else { - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } - } else if (sign == MINUS_BYTE) { // - 异常 - String bs = readString(buffer); - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } else { - String exstr = "Unknown reply: " + (char) sign; - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException(exstr)); - } - } catch (Exception e) { - failed(e, buffer); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer buffer) { - conn.offerBuffer(buffer); - transport.offerConnection(true, conn); - rsfuture.completeExceptionally(exc); - } - - }); - } catch (Exception e) { - failed(e, attachments); - } - } - - @Override - public void failed(Throwable exc, Void attachments) { - transport.offerConnection(true, conn); - rsfuture.completeExceptionally(exc); - } - }); - } catch (Exception e) { - rsfuture.completeExceptionally(e); - } - return rsfuture; - } -} - -abstract class ReplyCompletionHandler implements CompletionHandler { - - protected final ByteArray out = new ByteArray(); - - protected final AsyncConnection conn; - - public ReplyCompletionHandler(AsyncConnection conn) { - this.conn = conn; - } - - protected byte[] readBytes(ByteBuffer buffer) throws IOException { - readLine(buffer); - return out.getBytesAndClear(); - } - - protected String readString(ByteBuffer buffer) throws IOException { - readLine(buffer); - return out.toStringAndClear(null);//传null则表示使用StandardCharsets.UTF_8 - } - - protected int readInt(ByteBuffer buffer) throws IOException { - return (int) readLong(buffer); - } - - protected long readLong(ByteBuffer buffer) throws IOException { - readLine(buffer); - int start = 0; - if (out.get(0) == '$') start = 1; - boolean negative = out.get(start) == '-'; - long value = negative ? 0 : (out.get(start) - '0'); - for (int i = 1 + start; i < out.length(); i++) { - value = value * 10 + (out.get(i) - '0'); - } - out.clear(); - return negative ? -value : value; - } - - private void readLine(ByteBuffer buffer) throws IOException { - boolean has = buffer.hasRemaining(); - byte lasted = has ? buffer.get() : 0; - if (lasted == '\n' && !out.isEmpty() && out.getLastByte() == '\r') { - out.removeLastByte();//读掉 \r - buffer.get();//读掉 \n - return;//传null则表示使用StandardCharsets.UTF_8 - } - if (has) out.put(lasted); - while (buffer.hasRemaining()) { - byte b = buffer.get(); - if (b == '\n' && lasted == '\r') { - out.removeLastByte(); - return; - } - out.put(lasted = b); - } - //说明数据还没读取完 - buffer.clear(); - conn.readableByteChannel().read(buffer); - buffer.flip(); - readLine(buffer); - } - -} diff --git a/src/com/zdemo/cache_/RedisTest.java b/src/com/zdemo/cache_/RedisTest.java deleted file mode 100644 index bf441a7..0000000 --- a/src/com/zdemo/cache_/RedisTest.java +++ /dev/null @@ -1,262 +0,0 @@ -package com.zdemo.cache_; - -import com.zdemo.cachex.MyRedisCacheSource; -import org.redkale.convert.json.JsonFactory; -import org.redkale.net.AsyncIOGroup; -import org.redkale.util.AnyValue; -import org.redkale.util.ResourceFactory; - -import java.util.Map; - -import static org.redkale.boot.Application.RESNAME_APP_GROUP; - -public class RedisTest { - - static MyRedisCacheSource source; - static MyRedisCacheSource sourceInt; - - static { - AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue().addValue("maxconns", "10"); - conf.addValue("node", new AnyValue.DefaultAnyValue().addValue("addr", "47.111.150.118").addValue("port", "6064").addValue("password", "*Zhong9307!").addValue("db", 1)); - - final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16); - asyncGroup.start(); - ResourceFactory.root().register(RESNAME_APP_GROUP, asyncGroup); - - source = new MyRedisCacheSource(); - ResourceFactory.root().inject(source); - source.init(null); - source.defaultConvert = JsonFactory.root().getConvert(); - source.init(conf); - - // int - sourceInt = new MyRedisCacheSource(); - ResourceFactory.root().inject(sourceInt); - sourceInt.init(null); - sourceInt.defaultConvert = JsonFactory.root().getConvert(); - sourceInt.init(conf); - sourceInt.initValueType(Integer.class); - } - - public static void main(String[] args) { - - //System.out.println(source.remove("a", "b")); - - // bit - /*source.initValueType(Integer.class); - source.remove("a"); - boolean a = source.getBit("a", 1); - System.out.println(a); - - source.setBit("a", 1, true); - a = source.getBit("a", 1); - System.out.println("bit-a-1: " + a); - - source.setBit("a", 1, false); - a = source.getBit("a", 1); - System.out.println("bit-a-1: " + a);*/ - - /*source.remove("a"); - - // setnx - System.out.println(source.setnx("a", 1)); - source.remove("a"); - System.out.println(source.setnx("a", 1)); - - // set - source.remove("abx1"); - source.appendSetItems("abx1", "a", "b", "c"); - List list = source.srandomItems("abx1", 2); - String str = source.srandomItem("abx1"); //r - System.out.println(list);//[r1, r2] */ - - /*int[] arr = {0}; - ExecutorService executor = Executors.newFixedThreadPool(10); - CountDownLatch latch = new CountDownLatch(1000); - for (int i = 0; i < 1000; i++) { - executor.submit(() -> { - try { - source.lock("c", 1000); - arr[0]++; - // System.out.println("Thread: " + Thread.currentThread().getName()); - // Thread.sleep(10); - - } catch (Exception e) { - e.printStackTrace(); - } finally { - source.unlock("c"); - latch.countDown(); - } - }); - } - - try { - latch.await(); - System.out.println("n=" + arr[0]); - executor.shutdown(); - } catch (InterruptedException e) { - e.printStackTrace(); - }*/ - - - /*List list = (List) source.getCollection("gamerank-comment-stat"); - System.out.println(list);*/ - - /*for (int i = 0; i < 10; i++) { - String brpop = source.brpop("z", 2); - System.out.println(brpop); - }*/ - - // key 测试 - /*source.set("a", "123321"); - System.out.println(source.get("a")); // 123321 - System.out.println(source.getTtl("a")); // -1 - System.out.println(source.getPttl("a")); // -1 - System.out.println(source.getPttl("x")); // -2*/ - - // hashmap 测试 - /*source.remove("sk"); - source.setHm("sk", "a", "1"); - source.setHm("sk", "b", "2"); - System.out.println(source.getHm("sk", "a")); // 1 - source.remove("sk"); - - source.setHms("sk", Map.of("b", "5", "c", "3", "a", "1")); - source.hdel("sk", "a"); - - Map map = source.getHms("sk", "a", "x", "b", "c", "f"); // {b=5, c=3} - System.out.println(map); - System.out.println(source.getHmall("sk")); //{b=5, c=3} - System.out.println(source.incrHm("sk", "b", 1.1d)); // b = 6.1 - System.out.println(source.incrHm("sk", "c", 1)); // c = 4 - System.out.println(source.getHmall("sk")); //{b=6.1, c=4} - - System.out.println("--------------"); - System.out.println(source.hexists("sk", "b")); // true - System.out.println(source.getCollectionSize("sk")); // 2*/ - - - Map hms = source.getHms("supportusers", "5-kfeu0f", "xxxx", "3-0kbt7u8t", "95q- "); - hms.forEach((k, v) -> { - System.out.println(k + " : " + v); - }); - - - /*MyRedisCacheSource source2 = new MyRedisCacheSource(); - source2.defaultConvert = JsonFactory.root().getConvert(); - source2.initValueType(String.class); //value用String类型 - source2.init(conf);*/ - - /*Map gcMap = source.getHmall("hot-gamecomment"); - gcMap.forEach((k,v) -> { - System.out.println(k + " : " + v); - });*/ - - - //Map gameinfo = source.getHms("gameinfo", "22759", "22838", "10097", "22751", "22632", "22711", "22195", "15821", "10099", "16313", "11345", "10534", "22768", "22647", "22924", "18461", "15871", "17099", "22640", "22644", "10744", "10264", "18032", "22815", "13584", "10031", "22818", "22452", "22810", "10513", "10557", "15848", "11923", "15920", "22808", "20073", "22809", "15840", "12332", "15803", "10597", "22624", "17113", "19578", "22664", "22621", "20722", "16226", "10523", "12304", "10597","11923","10031"); - //Map gameinfo = source.getHms("gameinfo", "22759","22838","10097","22751","22632","22711","22195","15821","10099","16313","11345","10534","22768","22647","22924","18461","15871","17099","22363","22640","22644","10744","10264","18032","22815","13584","22818","22452","22810","10513","10557","15848","15920","22808","20073","22809","15840","12332","15803","10597","22624","17113","19578","22627","22664","22621","20722","16226","10523","12304"); - - /*gameinfo.forEach((k,v ) -> { - System.out.println(v); - });*/ - - - /*source.queryKeysStartsWith("articlebean:").forEach(x -> { - System.out.println(x); - //source.remove(x); - //System.out.println(source.getHmall(x)); - });*/ - - // list 测试 - /*sourceInt.remove("list"); - Collection list = sourceInt.getCollection("list"); - System.out.println(list); - for (int i = 1; i <= 10; i++) { - sourceInt.appendListItem("list", i); - } - System.out.println(sourceInt.getCollection("list")); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - - sourceInt.appendListItems("list", 11, 12, 13); - System.out.println(sourceInt.getCollection("list")); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - System.out.println(sourceInt.getCollection("list", 0, 5)); // [1, 2, 3, 4, 5] - System.out.println(sourceInt.getCollectionSize("list")); // 13 - - List ids = new ArrayList<>(100); - for (int i = 0; i < 2000; i++) { - ids.add(i); - } - sourceInt.remove("abx"); - sourceInt.appendListItems("abx", ids.toArray(Integer[]::new)); - System.out.println(sourceInt.getCollection("abx")); - */ - - /*System.out.println(sourceInt.getCollectionSize("recommend-user-quality")); - Collection uid = sourceInt.getCollection("recommend-user-quality"); - System.out.println(uid);*/ - - // zset 测试 - /*source.initValueType(String.class); //value用Integer类型 - source.remove("zx"); - source.zadd("zx", Map.of("a", 1, "b", 2)); - - source.zadd("zx", Map.of("a", 1, "c", 5L)); - source.zadd("zx", Map.of("x", 20, "j", 3.5)); - source.zadd("zx", Map.of("f", System.currentTimeMillis(), "c", 5L)); - source.zadd("zx", Map.of("a", 1, "c", 5L)); - - System.out.println(source.zincr("zx", "a", 1.34)); // 2.34 - System.out.println(source.getZsetDoubleScore("zx")); // {f=1592924555704, x=20, c=5, j=3, b=2.34, a=1} - source.zrem("zx", "b", "c", "e", "x"); - System.out.println(source.getZsetLongScore("zx")); // {f=1592924555704, j=3, a=2} - - System.out.println("--------------"); - System.out.println(source.getZsetLongScore("zx", "f")); - - System.out.println(source.getZrevrank("zx", "f")); // 0 - System.out.println(source.getZrank("zx", "f")); // 2 - System.out.println(source.getZrank("zx", "Y")); // -1 - System.out.println(source.getCollectionSize("zx")); // 3 - - System.out.println(source.getZset("zx")); - System.out.println(source.zexists("zx", "f", "x", "a"));*/ - - /*LocalDate date = LocalDate.of(2019, 12, 31); - for (int i = 0; i < 60; i++) { - LocalDate localDate = date.plusDays(-i); - String day = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE); - System.out.println(String.format("mkdir %s; mv *%s*.zip %s", day, day, day)); - }*/ - - - /*MyRedisCacheSource source = new MyRedisCacheSource(); - source.defaultConvert = JsonFactory.root().getConvert(); - source.initValueType(UserDetail.class); - source.init(conf); - - - Map map = source.getHmall("user-detail"); - - Integer[] array = map.values().stream().map(x -> x.getUserid()).toArray(Integer[]::new); - - System.out.println(JsonConvert.root().convertTo(array)); - - Map hms = source.getHms("user-detail", 11746, 11988, 11504, 11987, 11745, 11503, 11748, 11506, 11747, 11989, 11505, 11508, 11507, 11509, 11980, 11740, 11982, 11981, 11984, 11742, 11500, 11983, 11741, 11502, 11744, 11986, 11985, 11501, 11743, 11999, 11757, 11515, 1, 11514, 11998, 11756, 2, 11517, 11516, 11758, 3, 11519, 4, 5, 11518, 6, 7, 11991, 8, 11990, 9, 11993, 11751, 11750, 11992, 11753, 11511, 11995, 11994, 11510, 11752, 11755, 11513, 11997, 11512, 11996, 11754, 11724, 11966, 11965, 11723, 11968, 11726, 11967, 11725, 11728, 11969, 11727, 11729, 11960, 11720, 11962, 11961, 11722, 11964, 11721); - - System.out.println(hms.size());*/ - - /*source.getCollection("article-comment-list", 19, 1).forEach(x -> System.out.println(x)); - - - while (true) { - System.out.println("---" + Utility.now() + "---"); - source.getHmall("ck").forEach((k, v) -> { - System.out.println(k + ":" + v); - }); - try { - Thread.sleep(60 * 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }*/ - } -} diff --git a/src/com/zdemo/cachex/MyRedisCacheSource.java b/src/com/zdemo/cachex/MyRedisCacheSource.java deleted file mode 100644 index f08f311..0000000 --- a/src/com/zdemo/cachex/MyRedisCacheSource.java +++ /dev/null @@ -1,430 +0,0 @@ -package com.zdemo.cachex; - - -import org.redkale.convert.Convert; -import org.redkale.service.Local; -import org.redkale.source.CacheSource; -import org.redkale.util.AutoLoad; -import org.redkale.util.ResourceType; - -import java.io.Serializable; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Stream; - -@Local -@AutoLoad(false) -@ResourceType(CacheSource.class) -public class MyRedisCacheSource extends RedisCacheSource { - //--------------------- oth ------------------------------ - public boolean setnx(String key, Object v) { - byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Serializable rs = send("SETNX", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - return rs == null ? false : (long) rs == 1; - } - //--------------------- oth ------------------------------ - - //--------------------- bit ------------------------------ - public boolean getBit(String key, int offset) { - byte[][] bytes = Stream.of(key, offset).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Serializable v = send("GETBIT", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - return v == null ? false : (long) v == 1; - } - - public void setBit(String key, int offset, boolean bool) { - byte[][] bytes = Stream.of(key, offset, bool ? 1 : 0).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - send("SETBIT", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - } - - //--------------------- bit ------------------------------ - //--------------------- lock ------------------------------ - // 尝试加锁,成功返回0,否则返回上一锁剩余毫秒值 - public int tryLock(String key, int millis) { - byte[][] bytes = Stream.of("" + - "if (redis.call('exists',KEYS[1]) == 0) then " + - "redis.call('psetex', KEYS[1], ARGV[1], 1) " + - "return 0; " + - "else " + - "return redis.call('PTTL', KEYS[1]); " + - "end; ", 1, key, millis).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - int n = (int) send("EVAL", CacheEntryType.OBJECT, (Type) null, null, bytes).join(); - return n; - } - - // 加锁 - public void lock(String key, int millis) { - int i; - do { - i = tryLock(key, millis); - try { - Thread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } while (i > 0); - } - - // 解锁 - public void unlock(String key) { - remove(key); - } - - - //--------------------- key ------------------------------ - - public long getTtl(String key) { - return (long) send("TTL", CacheEntryType.OBJECT, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).join(); - } - - public long getPttl(String key) { - return (long) send("PTTL", CacheEntryType.OBJECT, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).join(); - } - - public int remove(String... keys) { - if (keys == null || keys.length == 0) { - return 0; - } - List para = new ArrayList<>(); - para.add("" + - " local args = ARGV;" + - " local x = 0;" + - " for i,v in ipairs(args) do" + - " local inx = redis.call('del', v);" + - " if(inx > 0) then" + - " x = x + 1;" + - " end" + - " end" + - " return x;"); - - para.add("0"); - for (Object field : keys) { - para.add(String.valueOf(field)); - } - byte[][] bytes = para.stream().map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - return (int) send("EVAL", CacheEntryType.OBJECT, (Type) null, null, bytes).join(); - } - - //--------------------- hmget ------------------------------ - public V getHm(String key, T field) { - // return (V) send("HMGET", CacheEntryType.OBJECT, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)).join(); - Map map = getHms(key, field); - return map.get(field); - } - - public Map getHms(String key, T... field) { - if (field == null || field.length == 0) { - return new HashMap<>(); - } - byte[][] bytes = Stream.concat(Stream.of(key), Stream.of(field)).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Map result = new HashMap<>(); - - List vs = (List) send("HMGET", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - for (int i = 0; i < field.length; i++) { // /*vs != null && vs.size() > i &&*/ - if (vs.get(i) == null) { - continue; - } - result.put(field[i], vs.get(i)); - } - - return result; - } - - public Map getHmall(String key) { - List vs = (List) send("HGETALL", CacheEntryType.OBJECT, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).join(); - Map result = new HashMap<>(vs.size() / 2); - for (int i = 0; i < vs.size(); i += 2) { - result.put(String.valueOf(vs.get(i)), vs.get(i + 1)); - } - - return result; - } - - //--------------------- hmset、hmdel、incr ------------------------------ - public void setHm(String key, T field, V value) { - byte[][] bytes = Stream.of(key, field, value).map(x -> x.toString().getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - send("HMSET", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - } - - public void setHms(String key, Map kv) { - List args = new ArrayList(); - args.add(key); - - kv.forEach((k, v) -> { - args.add(String.valueOf(k)); - args.add(String.valueOf(v)); - }); - - byte[][] bytes = args.stream().map(x -> x.getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - send("HMSET", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - } - - public Long incrHm(String key, T field, long n) { - byte[][] bytes = Stream.of(key, String.valueOf(field), String.valueOf(n)).map(x -> x.getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - return (Long) send("HINCRBY", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - } - - public Double incrHm(String key, T field, double n) { - byte[][] bytes = Stream.of(key, String.valueOf(field), String.valueOf(n)).map(x -> x.getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Serializable v = send("HINCRBYFLOAT", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - if (v == null) { - return null; - } - return Double.parseDouble(String.valueOf(v)); - } - - public void hdel(String key, T... field) { - byte[][] bytes = Stream.concat(Stream.of(key), Stream.of(field)).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - send("HDEL", null, (Type) null, key, bytes).join(); - } - - public List zexists(String key, T... fields) { - if (fields == null || fields.length == 0) { - return new ArrayList<>(); - } - List para = new ArrayList<>(); - para.add("" + - " local key = KEYS[1];" + - " local args = ARGV;" + - " local result = {};" + - " for i,v in ipairs(args) do" + - " local inx = redis.call('ZREVRANK', key, v);" + - " if(inx) then" + - " table.insert(result,1,v);" + - " end" + - " end" + - " return result;"); - para.add("1"); - para.add(key); - for (Object field : fields) { - para.add(String.valueOf(field)); - } - byte[][] bytes = para.stream().map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - return (List) send("EVAL", CacheEntryType.OBJECT, (Type) null, null, bytes).join(); - } - - //--------------------- set ------------------------------ - public T srandomItem(String key) { - byte[][] bytes = Stream.of(key, 1).map(x -> formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, x)).toArray(byte[][]::new); - List list = (List) send("SRANDMEMBER", null, (Type) null, key, bytes).join(); - return list != null && !list.isEmpty() ? list.get(0) : null; - } - - public List srandomItems(String key, int n) { - byte[][] bytes = Stream.of(key, n).map(x -> formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, x)).toArray(byte[][]::new); - return (List) send("SRANDMEMBER", null, (Type) null, key, bytes).join(); - } - - //--------------------- list ------------------------------ - public CompletableFuture appendListItemsAsync(String key, V... values) { - byte[][] bytes = Stream.concat(Stream.of(key), Stream.of(values)).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - return (CompletableFuture) send("RPUSH", null, (Type) null, key, bytes); - } - - public CompletableFuture lpushListItemAsync(String key, V value) { - return (CompletableFuture) send("LPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - public void lpushListItem(String key, V value) { - lpushListItemAsync(key, value).join(); - } - - public void appendListItems(String key, V... values) { - appendListItemsAsync(key, values).join(); - } - - public void appendSetItems(String key, V... values) { - // todo: - for (V v : values) { - appendSetItem(key, v); - } - } - - // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - public CompletableFuture> getCollectionAsync(String key, int offset, int limit) { - return (CompletableFuture) send("OBJECT", null, (Type) null, key, "ENCODING".getBytes(StandardCharsets.UTF_8), key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(null); - if (new String((byte[]) t).contains("list")) { //list - return send("LRANGE", CacheEntryType.OBJECT, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(offset).getBytes(StandardCharsets.UTF_8), String.valueOf(offset + limit - 1).getBytes(StandardCharsets.UTF_8)); - } else { - return send("SMEMBERS", CacheEntryType.OBJECT, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - public Collection getCollection(String key, int offset, int limit) { - return getCollectionAsync(key, offset, limit).join(); - } - - public V brpop(String key, int seconds) { - byte[][] bytes = Stream.concat(Stream.of(key), Stream.of(seconds)).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - return (V) send("BRPOP", null, (Type) null, key, bytes).join(); - } - - //--------------------- zset ------------------------------ - public void zadd(String key, Map kv) { - if (kv == null || kv.isEmpty()) { - return; - } - List args = new ArrayList(); - args.add(key); - - kv.forEach((k, v) -> { - args.add(String.valueOf(v)); - args.add(String.valueOf(k)); - }); - - byte[][] bytes = args.stream().map(x -> x.getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - send("ZADD", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - } - - public double zincr(String key, Object number, N n) { - byte[][] bytes = Stream.of(key, n, number).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Serializable v = send("ZINCRBY", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - return Double.parseDouble(String.valueOf(v)); - } - - public void zrem(String key, V... vs) { - List args = new ArrayList(); - args.add(key); - for (V v : vs) { - args.add(String.valueOf(v)); - } - byte[][] bytes = args.stream().map(x -> x.getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - send("ZREM", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - } - - public int getZrank(String key, V v) { - byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Long t = (Long) send("ZRANK", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - return t == null ? -1 : (int) (long) t; - } - - public int getZrevrank(String key, V v) { - byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Long t = (Long) send("ZREVRANK", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - return t == null ? -1 : (int) (long) t; - } - - //ZRANGE/ZREVRANGE key start stop - public List getZset(String key) { - byte[][] bytes = Stream.of(key, 0, -1).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - List vs2 = new ArrayList(vs.size()); - - for (int i = 0; i < vs.size(); ++i) { - if (i % 2 == 1) { - vs2.add(this.convert.convertFrom(this.objValueType, String.valueOf(vs.get(i)))); - } else { - vs2.add(vs.get(i)); - } - } - - return vs2; - } - - public List getZset(String key, int offset, int limit) { - byte[][] bytes = Stream.of(key, offset, offset + limit - 1).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - List vs2 = new ArrayList(vs.size()); - - for (int i = 0; i < vs.size(); ++i) { - if (i % 2 == 1) { - vs2.add(this.convert.convertFrom(this.objValueType, String.valueOf(vs.get(i)))); - } else { - vs2.add(vs.get(i)); - } - } - - return vs2; - } - - public LinkedHashMap getZsetLongScore(String key) { - LinkedHashMap map = getZsetDoubleScore(key); - if (map.isEmpty()) { - return new LinkedHashMap<>(); - } - - LinkedHashMap map2 = new LinkedHashMap<>(map.size()); - map.forEach((k, v) -> map2.put(k, (long) (double) v)); - return map2; - } - - public LinkedHashMap getZsetItemsLongScore(String key) { - byte[][] bytes = Stream.of(key, 0, -1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - LinkedHashMap map = new LinkedHashMap<>(); - for (int i = 0; i < vs.size(); i += 2) { - map.put((V) vs.get(i), (long) Double.parseDouble((String) vs.get(i + 1))); - } - return map; - } - - public Long getZsetLongScore(String key, V v) { - Double score = getZsetDoubleScore(key, v); - if (score == null) { - return null; - } - return (long) (double) score; - } - - public LinkedHashMap getZsetDoubleScore(String key) { - byte[][] bytes = Stream.of(key, 0, -1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - LinkedHashMap map = new LinkedHashMap<>(); - for (int i = 0; i < vs.size(); i += 2) { - map.put((V) vs.get(i), Double.parseDouble((String) vs.get(i + 1))); - } - return map; - } - - public Double getZsetDoubleScore(String key, V v) { - byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - Serializable zscore = send("ZSCORE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - if (zscore == null) { - return null; - } - - return Double.parseDouble(String.valueOf(zscore)); - } - - public LinkedHashMap getZsetLongScore(String key, int offset, int limit) { - byte[][] bytes = Stream.of(key, offset, offset + limit - 1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - LinkedHashMap map = new LinkedHashMap<>(); - for (int i = 0; i < vs.size(); i += 2) { - map.put((V) vs.get(i), (long) Double.parseDouble((String) vs.get(i + 1))); - } - return map; - } - - public LinkedHashMap getZsetDoubleScore(String key, int offset, int limit) { - byte[][] bytes = Stream.of(key, offset, offset + limit - 1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); - List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); - - LinkedHashMap map = new LinkedHashMap<>(); - for (int i = 0; i < vs.size(); i += 2) { - map.put((V) vs.get(i), Double.parseDouble(vs.get(i + 1) + "")); - } - return map; - } - - // ---------- - protected byte[] formatValue(CacheEntryType cacheType, Convert convert0, Type resultType, Object value) { - if (value == null) return "null".getBytes(StandardCharsets.UTF_8); - if (convert0 == null) convert0 = convert; - if (cacheType == CacheEntryType.LONG || cacheType == CacheEntryType.ATOMIC) - return String.valueOf(value).getBytes(StandardCharsets.UTF_8); - if (cacheType == CacheEntryType.STRING) return convert0.convertToBytes(String.class, value); - - if (value instanceof String) return String.valueOf(value).getBytes(StandardCharsets.UTF_8); - if (value instanceof Number) return String.valueOf(value).getBytes(StandardCharsets.UTF_8); - return convert0.convertToBytes(resultType == null ? objValueType : resultType, value); - } -} diff --git a/src/com/zdemo/cachex/RedisCacheSource.java b/src/com/zdemo/cachex/RedisCacheSource.java deleted file mode 100644 index fcbe6a4..0000000 --- a/src/com/zdemo/cachex/RedisCacheSource.java +++ /dev/null @@ -1,2240 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.zdemo.cachex; - -import org.redkale.convert.Convert; -import org.redkale.convert.bson.BsonByteBufferWriter; -import org.redkale.convert.json.JsonConvert; -import org.redkale.convert.json.JsonFactory; -import org.redkale.net.AsyncConnection; -import org.redkale.net.Transport; -import org.redkale.net.TransportFactory; -import org.redkale.service.AbstractService; -import org.redkale.service.Local; -import org.redkale.service.Service; -import org.redkale.source.CacheSource; -import org.redkale.source.Flipper; -import org.redkale.util.*; -import org.redkale.util.AnyValue.DefaultAnyValue; - -import javax.annotation.Resource; -import java.io.IOException; -import java.io.Serializable; -import java.lang.reflect.Type; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.CompletionHandler; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Semaphore; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * 详情见: https://redkale.org - * - * @param Value - * @author zhangjx - */ -@Local -@AutoLoad(false) -@ResourceType(CacheSource.class) -public class RedisCacheSource extends AbstractService implements CacheSource, Service, AutoCloseable, Resourcable { - - protected static final byte DOLLAR_BYTE = '$'; - - protected static final byte ASTERISK_BYTE = '*'; - - protected static final byte PLUS_BYTE = '+'; - - protected static final byte MINUS_BYTE = '-'; - - protected static final byte COLON_BYTE = ':'; - - private final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - - @Resource - protected JsonConvert defaultConvert; - - @Resource(name = "$_convert") - protected JsonConvert convert; - - protected Type objValueType = String.class; - - protected Map passwords; - - protected List nodeAddrs; - - protected int db; - - protected Transport transport; - - @Override - public void init(AnyValue conf) { - if (this.convert == null) this.convert = this.defaultConvert; - if (conf == null) conf = new AnyValue.DefaultAnyValue(); - - AnyValue prop = conf.getAnyValue("properties"); - if (prop != null) { - String storeValueStr = prop.getValue("value-type"); - if (storeValueStr != null) { - try { - this.initValueType(Thread.currentThread().getContextClassLoader().loadClass(storeValueStr)); - } catch (Throwable e) { - logger.log(Level.SEVERE, this.getClass().getSimpleName() + " load key & value store class (" + storeValueStr + ") error", e); - } - } - } - final int bufferCapacity = conf.getIntValue("bufferCapacity", 8 * 1024); - final int bufferPoolSize = conf.getIntValue("bufferPoolSize", Runtime.getRuntime().availableProcessors() * 8); - final int threads = conf.getIntValue("threads", Runtime.getRuntime().availableProcessors() * 8); - final int readTimeoutSeconds = conf.getIntValue("readTimeoutSeconds", TransportFactory.DEFAULT_READTIMEOUTSECONDS); - final int writeTimeoutSeconds = conf.getIntValue("writeTimeoutSeconds", TransportFactory.DEFAULT_WRITETIMEOUTSECONDS); - final List addresses = new ArrayList<>(); - Map passwords0 = new HashMap<>(); - for (AnyValue node : conf.getAnyValues("node")) { - String addrstr = node.getValue("addr"); - InetSocketAddress addr = null; - if (addrstr.startsWith("redis://")) { - addrstr = addrstr.substring("redis://".length()); - int pos = addrstr.indexOf(':'); - addr = new InetSocketAddress(addrstr.substring(0, pos), Integer.parseInt(addrstr.substring(pos + 1))); - addresses.add(addr); - } else { - addr = new InetSocketAddress(addrstr, node.getIntValue("port")); - addresses.add(addr); - } - String password = node.getValue("password", "").trim(); - if (!password.isEmpty()) passwords0.put(addr, password.getBytes(StandardCharsets.UTF_8)); - String db0 = node.getValue("db", "").trim(); - if (!db0.isEmpty()) this.db = Integer.valueOf(db0); - } - if (!passwords0.isEmpty()) this.passwords = passwords0; - this.nodeAddrs = addresses; - TransportFactory transportFactory = TransportFactory.create(threads, bufferPoolSize, bufferCapacity, readTimeoutSeconds, writeTimeoutSeconds); - this.transport = transportFactory.createTransportTCP("Redis-Transport", null, addresses); - this.transport.setSemaphore(new Semaphore(conf.getIntValue("maxconns", threads))); - if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, RedisCacheSource.class.getSimpleName() + ": addrs=" + addresses + ", db=" + db); - - } - - @Override //ServiceLoader时判断配置是否符合当前实现类 - public boolean match(AnyValue config) { - if (config == null) return false; - AnyValue[] nodes = config.getAnyValues("node"); - if (nodes == null || nodes.length == 0) return false; - for (AnyValue node : nodes) { - if (node.getValue("addr") != null && node.getValue("port") != null) return true; - if (node.getValue("addr") != null && node.getValue("addr").startsWith("redis://")) return true; - } - return false; - } - - public void updateRemoteAddresses(final Collection addresses) { - this.transport.updateRemoteAddresses(addresses); - } - - @Override - @Deprecated - public final void initValueType(Type valueType) { - this.objValueType = valueType == null ? String.class : valueType; - } - - @Override - @Deprecated - public final void initTransient(boolean flag) { - } - - @Override - public final String getType() { - return "redis"; - } - - public static void main(String[] args) throws Exception { - DefaultAnyValue conf = new DefaultAnyValue().addValue("maxconns", "1"); - conf.addValue("node", new DefaultAnyValue().addValue("addr", "127.0.0.1").addValue("port", "6363")); - - RedisCacheSource source = new RedisCacheSource(); - source.defaultConvert = JsonFactory.root().getConvert(); - source.init(conf); - InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 7788); - try { - System.out.println("------------------------------------"); - source.removeAsync("stritem1"); - source.removeAsync("stritem2"); - source.setStringAsync("stritem1", "value1"); - source.setStringAsync("stritem2", "value2"); - System.out.println("stritem开头的key有两个: " + source.queryKeysStartsWith("stritem")); - System.out.println("[有值] MGET : " + source.getStringMap("stritem1", "stritem2")); - System.out.println("[有值] MGET : " + Arrays.toString(source.getStringArray("stritem1", "stritem2"))); - - source.remove("intitem1"); - source.remove("intitem2"); - source.setLong("intitem1", 333); - source.setLong("intitem2", 444); - System.out.println("[有值] MGET : " + source.getStringMap("intitem1", "intitem22", "intitem2")); - System.out.println("[有值] MGET : " + Arrays.toString(source.getStringArray("intitem1", "intitem22", "intitem2"))); - source.remove("objitem1"); - source.remove("objitem2"); - source.set("objitem1", Flipper.class, new Flipper(10)); - source.set("objitem2", Flipper.class, new Flipper(20)); - System.out.println("[有值] MGET : " + source.getMap(Flipper.class, "objitem1", "objitem2")); - - source.remove("key1"); - source.remove("key2"); - source.remove("300"); - source.set(1000, "key1", String.class, "value1"); - source.set("key1", String.class, "value1"); - source.setString("keystr1", "strvalue1"); - source.setLong("keylong1", 333L); - source.set("300", String.class, "4000"); - source.getAndRefresh("key1", 3500, String.class); - System.out.println("[有值] 300 GET : " + source.get("300", String.class)); - System.out.println("[有值] key1 GET : " + source.get("key1", String.class)); - System.out.println("[无值] key2 GET : " + source.get("key2", String.class)); - System.out.println("[有值] keystr1 GET : " + source.getString("keystr1")); - System.out.println("[有值] keylong1 GET : " + source.getLong("keylong1", 0L)); - System.out.println("[有值] key1 EXISTS : " + source.exists("key1")); - System.out.println("[无值] key2 EXISTS : " + source.exists("key2")); - - source.remove("keys3"); - source.appendListItem("keys3", String.class, "vals1"); - source.appendListItem("keys3", String.class, "vals2"); - System.out.println("-------- keys3 追加了两个值 --------"); - System.out.println("[两值] keys3 VALUES : " + source.getCollection("keys3", String.class)); - System.out.println("[有值] keys3 EXISTS : " + source.exists("keys3")); - source.removeListItem("keys3", String.class, "vals1"); - System.out.println("[一值] keys3 VALUES : " + source.getCollection("keys3", String.class)); - source.getCollectionAndRefresh("keys3", 3000, String.class); - - source.remove("stringmap"); - source.appendSetItem("stringmap", JsonConvert.TYPE_MAP_STRING_STRING, Utility.ofMap("a", "aa", "b", "bb")); - source.appendSetItem("stringmap", JsonConvert.TYPE_MAP_STRING_STRING, Utility.ofMap("c", "cc", "d", "dd")); - System.out.println("[两值] stringmap VALUES : " + source.getCollectionAsync("stringmap", JsonConvert.TYPE_MAP_STRING_STRING).join()); - - source.remove("sets3"); - source.remove("sets4"); - source.appendSetItem("sets3", String.class, "setvals1"); - source.appendSetItem("sets3", String.class, "setvals2"); - source.appendSetItem("sets3", String.class, "setvals1"); - source.appendSetItem("sets4", String.class, "setvals2"); - source.appendSetItem("sets4", String.class, "setvals1"); - System.out.println("[两值] sets3 VALUES : " + source.getCollection("sets3", String.class)); - System.out.println("[有值] sets3 EXISTS : " + source.exists("sets3")); - System.out.println("[有值] sets3-setvals2 EXISTSITEM : " + source.existsSetItem("sets3", String.class, "setvals2")); - System.out.println("[有值] sets3-setvals3 EXISTSITEM : " + source.existsSetItem("sets3", String.class, "setvals3")); - source.removeSetItem("sets3", String.class, "setvals1"); - System.out.println("[一值] sets3 VALUES : " + source.getCollection("sets3", String.class)); - System.out.println("sets3 大小 : " + source.getCollectionSize("sets3")); - System.out.println("all keys: " + source.queryKeys()); - System.out.println("key startkeys: " + source.queryKeysStartsWith("key")); - System.out.println("newnum 值 : " + source.incr("newnum")); - System.out.println("newnum 值 : " + source.decr("newnum")); - System.out.println("sets3&sets4: " + source.getStringCollectionMap(true, "sets3", "sets4")); - System.out.println("------------------------------------"); - source.set("myaddr", InetSocketAddress.class, addr); - System.out.println("myaddrstr: " + source.getString("myaddr")); - System.out.println("myaddr: " + source.get("myaddr", InetSocketAddress.class)); - source.remove("myaddrs"); - source.remove("myaddrs2"); - source.appendSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788)); - source.appendSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7799)); - System.out.println("myaddrs: " + source.getCollection("myaddrs", InetSocketAddress.class)); - source.removeSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788)); - System.out.println("myaddrs: " + source.getCollection("myaddrs", InetSocketAddress.class)); - source.appendSetItem("myaddrs2", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788)); - source.appendSetItem("myaddrs2", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7799)); - System.out.println("myaddrs&myaddrs2: " + source.getCollectionMap(true, InetSocketAddress.class, "myaddrs", "myaddrs2")); - System.out.println("------------------------------------"); - source.remove("myaddrs"); - Type mapType = new TypeToken>() { - }.getType(); - Map map = new HashMap<>(); - map.put("a", 1); - map.put("b", 2); - source.set("mapvals", mapType, map); - System.out.println("mapvals: " + source.get("mapvals", mapType)); - - source.remove("byteskey"); - source.setBytes("byteskey", new byte[]{1, 2, 3}); - System.out.println("byteskey 值 : " + Arrays.toString(source.getBytes("byteskey"))); - //h - source.remove("hmap"); - source.hincr("hmap", "key1"); - System.out.println("hmap.key1 值 : " + source.hgetLong("hmap", "key1", -1)); - source.hmset("hmap", "key2", "haha", "key3", 333); - source.hmset("hmap", "sm", (HashMap) Utility.ofMap("a", "aa", "b", "bb")); - System.out.println("hmap.sm 值 : " + source.hget("hmap", "sm", JsonConvert.TYPE_MAP_STRING_STRING)); - System.out.println("hmap.[key1,key2,key3] 值 : " + source.hmget("hmap", String.class, "key1", "key2", "key3")); - System.out.println("hmap.keys 四值 : " + source.hkeys("hmap")); - source.hremove("hmap", "key1", "key3"); - System.out.println("hmap.keys 两值 : " + source.hkeys("hmap")); - System.out.println("hmap.key2 值 : " + source.hgetString("hmap", "key2")); - System.out.println("hmap列表(2)大小 : " + source.hsize("hmap")); - - source.remove("hmaplong"); - source.hincr("hmaplong", "key1", 10); - source.hsetLong("hmaplong", "key2", 30); - System.out.println("hmaplong.所有两值 : " + source.hmap("hmaplong", long.class, 0, 10)); - - source.remove("hmapstr"); - source.hsetString("hmapstr", "key1", "str10"); - source.hsetString("hmapstr", "key2", null); - System.out.println("hmapstr.所有一值 : " + source.hmap("hmapstr", String.class, 0, 10)); - - source.remove("hmapstrmap"); - source.hset("hmapstrmap", "key1", JsonConvert.TYPE_MAP_STRING_STRING, (HashMap) Utility.ofMap("ks11", "vv11")); - source.hset("hmapstrmap", "key2", JsonConvert.TYPE_MAP_STRING_STRING, null); - System.out.println("hmapstrmap.无值 : " + source.hmap("hmapstrmap", JsonConvert.TYPE_MAP_STRING_STRING, 0, 10, "key2*")); - - source.remove("popset"); - source.appendStringSetItem("popset", "111"); - source.appendStringSetItem("popset", "222"); - source.appendStringSetItem("popset", "333"); - source.appendStringSetItem("popset", "444"); - source.appendStringSetItem("popset", "555"); - System.out.println("SPOP一个元素:" + source.spopStringSetItem("popset")); - System.out.println("SPOP两个元素:" + source.spopStringSetItem("popset", 2)); - System.out.println("SPOP五个元素:" + source.spopStringSetItem("popset", 5)); - source.appendLongSetItem("popset", 111); - source.appendLongSetItem("popset", 222); - source.appendLongSetItem("popset", 333); - source.appendLongSetItem("popset", 444); - source.appendLongSetItem("popset", 555); - System.out.println("SPOP一个元素:" + source.spopLongSetItem("popset")); - System.out.println("SPOP两个元素:" + source.spopLongSetItem("popset", 2)); - System.out.println("SPOP五个元素:" + source.spopLongSetItem("popset", 5)); - System.out.println("SPOP一个元素:" + source.spopLongSetItem("popset")); - - //清除 - int rs = source.remove("stritem1"); - System.out.println("删除stritem1个数: " + rs); - source.remove("popset"); - source.remove("stritem2"); - source.remove("intitem1"); - source.remove("intitem2"); - source.remove("keylong1"); - source.remove("keystr1"); - source.remove("mapvals"); - source.remove("myaddr"); - source.remove("myaddrs2"); - source.remove("newnum"); - source.remove("objitem1"); - source.remove("objitem2"); - source.remove("key1"); - source.remove("key2"); - source.remove("keys3"); - source.remove("sets3"); - source.remove("sets4"); - source.remove("myaddrs"); - source.remove("300"); - source.remove("stringmap"); - source.remove("hmap"); - source.remove("hmaplong"); - source.remove("hmapstr"); - source.remove("hmapstrmap"); - source.remove("byteskey"); - System.out.println("------------------------------------"); -// System.out.println("--------------测试大文本---------------"); -// HashMap bigmap = new HashMap<>(); -// StringBuilder sb = new StringBuilder(); -// sb.append("起始"); -// for (int i = 0; i < 1024 * 1024; i++) { -// sb.append("abcde"); -// } -// sb.append("结束"); -// bigmap.put("val", sb.toString()); -// System.out.println("文本长度: " + sb.length()); -// source.set("bigmap", JsonConvert.TYPE_MAP_STRING_STRING, bigmap); -// System.out.println("写入完成"); -// for (int i = 0; i < 1; i++) { -// HashMap fs = (HashMap) source.get("bigmap", JsonConvert.TYPE_MAP_STRING_STRING); -// System.out.println("内容长度: " + fs.get("val").length()); -// } - source.remove("bigmap"); - - } finally { - source.close(); - } - } - - @Override - public void close() throws Exception { //在 Application 关闭时调用 - destroy(null); - } - - @Override - public String resourceName() { - Resource res = this.getClass().getAnnotation(Resource.class); - return res == null ? "" : res.name(); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{addrs = " + this.nodeAddrs + ", db=" + this.db + "}"; - } - - @Override - public void destroy(AnyValue conf) { - if (transport != null) transport.close(); - } - - //--------------------- exists ------------------------------ - @Override - public CompletableFuture existsAsync(String key) { - return (CompletableFuture) send("EXISTS", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public boolean exists(String key) { - return existsAsync(key).join(); - } - - //--------------------- get ------------------------------ - @Override - @Deprecated - public CompletableFuture getAsync(String key) { - return (CompletableFuture) send("GET", CacheEntryType.OBJECT, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture getAsync(String key, Type type) { - return (CompletableFuture) send("GET", CacheEntryType.OBJECT, type, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture getStringAsync(String key) { - return (CompletableFuture) send("GET", CacheEntryType.STRING, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture getLongAsync(String key, long defValue) { - return ((CompletableFuture) send("GET", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8))).thenApplyAsync(v -> v == null ? defValue : v); - } - - @Override - @Deprecated - public V get(String key) { - return getAsync(key).join(); - } - - @Override - public T get(String key, final Type type) { - return (T) getAsync(key, type).join(); - } - - @Override - public String getString(String key) { - return getStringAsync(key).join(); - } - - @Override - public long getLong(String key, long defValue) { - return getLongAsync(key, defValue).join(); - } - - //--------------------- getAndRefresh ------------------------------ - @Override - @Deprecated - public CompletableFuture getAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getAsync(key)); - } - - @Override - public CompletableFuture getAndRefreshAsync(String key, int expireSeconds, final Type type) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getAsync(key, type)); - } - - @Override - @Deprecated - public V getAndRefresh(String key, final int expireSeconds) { - return getAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public T getAndRefresh(String key, final int expireSeconds, final Type type) { - return (T) getAndRefreshAsync(key, expireSeconds, type).join(); - } - - @Override - public CompletableFuture getStringAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getStringAsync(key)); - } - - @Override - public String getStringAndRefresh(String key, final int expireSeconds) { - return getStringAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public CompletableFuture getLongAndRefreshAsync(String key, int expireSeconds, long defValue) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getLongAsync(key, defValue)); - } - - @Override - public long getLongAndRefresh(String key, final int expireSeconds, long defValue) { - return getLongAndRefreshAsync(key, expireSeconds, defValue).join(); - } - - //--------------------- refresh ------------------------------ - @Override - public CompletableFuture refreshAsync(String key, int expireSeconds) { - return setExpireSecondsAsync(key, expireSeconds); - } - - @Override - public void refresh(String key, final int expireSeconds) { - setExpireSeconds(key, expireSeconds); - } - - //--------------------- set ------------------------------ - @Override - @Deprecated - public CompletableFuture setAsync(String key, V value) { - CacheEntryType cet = this.objValueType == String.class ? CacheEntryType.STRING : CacheEntryType.OBJECT; - return (CompletableFuture) send("SET", cet, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture setAsync(String key, Convert convert, T value) { - CacheEntryType cet = value instanceof CharSequence ? CacheEntryType.STRING : CacheEntryType.OBJECT; - return (CompletableFuture) send("SET", cet, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, convert, (Type) null, value)); - } - - @Override - public CompletableFuture setAsync(String key, final Type type, T value) { - CacheEntryType cet = type == String.class ? CacheEntryType.STRING : CacheEntryType.OBJECT; - return (CompletableFuture) send("SET", cet, type, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, (Convert) null, type, value)); - } - - @Override - public CompletableFuture setAsync(String key, Convert convert, final Type type, T value) { - CacheEntryType cet = type == String.class ? CacheEntryType.STRING : CacheEntryType.OBJECT; - return (CompletableFuture) send("SET", cet, type, key, key.getBytes(StandardCharsets.UTF_8), formatValue(cet, convert, type, value)); - } - - @Override - @Deprecated - public void set(final String key, V value) { - setAsync(key, value).join(); - } - - @Override - public void set(final String key, final Convert convert, T value) { - setAsync(key, convert, value).join(); - } - - @Override - public void set(final String key, final Type type, T value) { - setAsync(key, type, value).join(); - } - - @Override - public void set(String key, final Convert convert, final Type type, T value) { - setAsync(key, convert, type, value).join(); - } - - @Override - public CompletableFuture setStringAsync(String key, String value) { - return (CompletableFuture) send("SET", CacheEntryType.STRING, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public void setString(String key, String value) { - setStringAsync(key, value).join(); - } - - @Override - public CompletableFuture setLongAsync(String key, long value) { - return (CompletableFuture) send("SET", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public void setLong(String key, long value) { - setLongAsync(key, value).join(); - } - - //--------------------- set ------------------------------ - @Override - @Deprecated - public CompletableFuture setAsync(int expireSeconds, String key, V value) { - return (CompletableFuture) setAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture setAsync(int expireSeconds, String key, Convert convert, T value) { - return (CompletableFuture) setAsync(key, convert, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture setAsync(int expireSeconds, String key, final Type type, T value) { - return (CompletableFuture) setAsync(key, type, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture setAsync(int expireSeconds, String key, Convert convert, final Type type, T value) { - return (CompletableFuture) setAsync(key, convert, type, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - @Deprecated - public void set(int expireSeconds, String key, V value) { - setAsync(expireSeconds, key, value).join(); - } - - @Override - public void set(int expireSeconds, String key, Convert convert, T value) { - setAsync(expireSeconds, key, convert, value).join(); - } - - @Override - public void set(int expireSeconds, String key, final Type type, T value) { - setAsync(expireSeconds, key, type, value).join(); - } - - @Override - public void set(int expireSeconds, String key, Convert convert, final Type type, T value) { - setAsync(expireSeconds, key, convert, type, value).join(); - } - - @Override - public CompletableFuture setStringAsync(int expireSeconds, String key, String value) { - return (CompletableFuture) setStringAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public void setString(int expireSeconds, String key, String value) { - setStringAsync(expireSeconds, key, value).join(); - } - - @Override - public CompletableFuture setLongAsync(int expireSeconds, String key, long value) { - return (CompletableFuture) setLongAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public void setLong(int expireSeconds, String key, long value) { - setLongAsync(expireSeconds, key, value).join(); - } - - //--------------------- setExpireSeconds ------------------------------ - @Override - public CompletableFuture setExpireSecondsAsync(String key, int expireSeconds) { - return (CompletableFuture) send("EXPIRE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public void setExpireSeconds(String key, int expireSeconds) { - setExpireSecondsAsync(key, expireSeconds).join(); - } - - //--------------------- remove ------------------------------ - @Override - public CompletableFuture removeAsync(String key) { - return (CompletableFuture) send("DEL", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public int remove(String key) { - return removeAsync(key).join(); - } - - //--------------------- incr ------------------------------ - @Override - public long incr(final String key) { - return incrAsync(key).join(); - } - - @Override - public CompletableFuture incrAsync(final String key) { - return (CompletableFuture) send("INCR", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public long incr(final String key, long num) { - return incrAsync(key, num).join(); - } - - @Override - public CompletableFuture incrAsync(final String key, long num) { - return (CompletableFuture) send("INCRBY", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)); - } - - //--------------------- decr ------------------------------ - @Override - public long decr(final String key) { - return decrAsync(key).join(); - } - - @Override - public CompletableFuture decrAsync(final String key) { - return (CompletableFuture) send("DECR", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public long decr(final String key, long num) { - return decrAsync(key, num).join(); - } - - @Override - public CompletableFuture decrAsync(final String key, long num) { - return (CompletableFuture) send("DECRBY", CacheEntryType.ATOMIC, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public int hremove(final String key, String... fields) { - return hremoveAsync(key, fields).join(); - } - - @Override - public int hsize(final String key) { - return hsizeAsync(key).join(); - } - - @Override - public List hkeys(final String key) { - return hkeysAsync(key).join(); - } - - @Override - public long hincr(final String key, String field) { - return hincrAsync(key, field).join(); - } - - @Override - public long hincr(final String key, String field, long num) { - return hincrAsync(key, field, num).join(); - } - - @Override - public long hdecr(final String key, String field) { - return hdecrAsync(key, field).join(); - } - - @Override - public long hdecr(final String key, String field, long num) { - return hdecrAsync(key, field, num).join(); - } - - @Override - public boolean hexists(final String key, String field) { - return hexistsAsync(key, field).join(); - } - - @Override - public void hset(final String key, final String field, final Convert convert, final T value) { - hsetAsync(key, field, convert, value).join(); - } - - @Override - public void hset(final String key, final String field, final Type type, final T value) { - hsetAsync(key, field, type, value).join(); - } - - @Override - public void hset(final String key, final String field, final Convert convert, final Type type, final T value) { - hsetAsync(key, field, convert, type, value).join(); - } - - @Override - public void hsetString(final String key, final String field, final String value) { - hsetStringAsync(key, field, value).join(); - } - - @Override - public void hsetLong(final String key, final String field, final long value) { - hsetLongAsync(key, field, value).join(); - } - - @Override - public void hmset(final String key, final Serializable... values) { - hmsetAsync(key, values).join(); - } - - @Override - public List hmget(final String key, final Type type, final String... fields) { - return hmgetAsync(key, type, fields).join(); - } - - @Override - public Map hmap(final String key, final Type type, int offset, int limit, String pattern) { - return (Map) hmapAsync(key, type, offset, limit, pattern).join(); - } - - @Override - public Map hmap(final String key, final Type type, int offset, int limit) { - return (Map) hmapAsync(key, type, offset, limit).join(); - } - - @Override - public T hget(final String key, final String field, final Type type) { - return (T) hgetAsync(key, field, type).join(); - } - - @Override - public String hgetString(final String key, final String field) { - return hgetStringAsync(key, field).join(); - } - - @Override - public long hgetLong(final String key, final String field, long defValue) { - return hgetLongAsync(key, field, defValue).join(); - } - - @Override - public CompletableFuture hremoveAsync(final String key, String... fields) { - byte[][] bs = new byte[fields.length + 1][]; - bs[0] = key.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < fields.length; i++) { - bs[i + 1] = fields[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("HDEL", CacheEntryType.MAP, (Type) null, key, bs); - } - - @Override - public CompletableFuture hsizeAsync(final String key) { - return (CompletableFuture) send("HLEN", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> hkeysAsync(final String key) { - return (CompletableFuture) send("HKEYS", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hincrAsync(final String key, String field) { - return hincrAsync(key, field, 1); - } - - @Override - public CompletableFuture hincrAsync(final String key, String field, long num) { - return (CompletableFuture) send("HINCRBY", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hdecrAsync(final String key, String field) { - return hincrAsync(key, field, -1); - } - - @Override - public CompletableFuture hdecrAsync(final String key, String field, long num) { - return hincrAsync(key, field, -num); - } - - @Override - public CompletableFuture hexistsAsync(final String key, String field) { - return (CompletableFuture) send("HEXISTS", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Convert convert, final T value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.MAP, convert, null, value)); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Type type, final T value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, type, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.MAP, null, type, value)); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Convert convert, final Type type, final T value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, type, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.MAP, convert, type, value)); - } - - @Override - public CompletableFuture hsetStringAsync(final String key, final String field, final String value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, null, null, value)); - } - - @Override - public CompletableFuture hsetLongAsync(final String key, final String field, final long value) { - return (CompletableFuture) send("HSET", CacheEntryType.MAP, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, null, null, value)); - } - - @Override - public CompletableFuture hmsetAsync(final String key, final Serializable... values) { - byte[][] bs = new byte[values.length + 1][]; - bs[0] = key.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < values.length; i += 2) { - bs[i + 1] = String.valueOf(values[i]).getBytes(StandardCharsets.UTF_8); - bs[i + 2] = formatValue(CacheEntryType.MAP, null, null, values[i + 1]); - } - return (CompletableFuture) send("HMSET", CacheEntryType.MAP, (Type) null, key, bs); - } - - @Override - public CompletableFuture> hmgetAsync(final String key, final Type type, final String... fields) { - byte[][] bs = new byte[fields.length + 1][]; - bs[0] = key.getBytes(StandardCharsets.UTF_8); - for (int i = 0; i < fields.length; i++) { - bs[i + 1] = fields[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("HMGET", CacheEntryType.MAP, type, key, bs); - } - - @Override - public CompletableFuture> hmapAsync(final String key, final Type type, int offset, int limit) { - return hmapAsync(key, type, offset, limit, null); - } - - @Override - public CompletableFuture> hmapAsync(final String key, final Type type, int offset, int limit, String pattern) { - byte[][] bs = new byte[pattern == null || pattern.isEmpty() ? 4 : 6][limit]; - int index = -1; - bs[++index] = key.getBytes(StandardCharsets.UTF_8); - bs[++index] = String.valueOf(offset).getBytes(StandardCharsets.UTF_8); - if (pattern != null && !pattern.isEmpty()) { - bs[++index] = "MATCH".getBytes(StandardCharsets.UTF_8); - bs[++index] = pattern.getBytes(StandardCharsets.UTF_8); - } - bs[++index] = "COUNT".getBytes(StandardCharsets.UTF_8); - bs[++index] = String.valueOf(limit).getBytes(StandardCharsets.UTF_8); - return (CompletableFuture) send("HSCAN", CacheEntryType.MAP, type, key, bs); - } - - @Override - public CompletableFuture hgetAsync(final String key, final String field, final Type type) { - return (CompletableFuture) send("HGET", CacheEntryType.OBJECT, type, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hgetStringAsync(final String key, final String field) { - return (CompletableFuture) send("HGET", CacheEntryType.STRING, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture hgetLongAsync(final String key, final String field, long defValue) { - return (CompletableFuture) send("HGET", CacheEntryType.LONG, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)).thenApplyAsync(v -> v == null ? defValue : v); - } - - //--------------------- collection ------------------------------ - @Override - public CompletableFuture getCollectionSizeAsync(String key) { - return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(0); - String rs = new String((byte[]) t); - if (rs.contains("zset")) { // ziplist - return send("ZCARD", null, int.class, key, key.getBytes(StandardCharsets.UTF_8)); - } else if (rs.contains("list")) { //list - return send("LLEN", null, int.class, key, key.getBytes(StandardCharsets.UTF_8)); - } else if (rs.contains("hash")) { - return send("HLEN", null, int.class, key, key.getBytes(StandardCharsets.UTF_8)); - } else { - return send("SCARD", null, int.class, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public int getCollectionSize(String key) { - return getCollectionSizeAsync(key).join(); - } - - @Override - @Deprecated - public CompletableFuture> getCollectionAsync(String key) { - return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(null); - String str = new String((byte[]) t); - if (str.contains("list")) { //list - return send("LRANGE", CacheEntryType.OBJECT, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}); - } else if (str.contains("none")) { - return CompletableFuture.completedFuture(new ArrayList<>()); - } else { - return send("SMEMBERS", CacheEntryType.OBJECT, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public CompletableFuture> getCollectionAsync(String key, final Type componentType) { - return (CompletableFuture) send("TYPE", null, componentType, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(null); - if (new String((byte[]) t).contains("list")) { //list - return send("LRANGE", CacheEntryType.OBJECT, componentType, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}); - } else { - return send("SMEMBERS", CacheEntryType.OBJECT, componentType, true, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public CompletableFuture> getLongMapAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.LONG, null, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - Map map = new LinkedHashMap<>(); - for (int i = 0; i < keys.length; i++) { - Object obj = list.get(i); - if (obj != null) map.put(keys[i], list.get(i)); - } - return map; - }); - } - - @Override - public CompletableFuture getLongArrayAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.LONG, null, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - Long[] rs = new Long[keys.length]; - for (int i = 0; i < keys.length; i++) { - Number obj = (Number) list.get(i); - rs[i] = obj == null ? null : obj.longValue(); - } - return rs; - }); - } - - @Override - public CompletableFuture getStringArrayAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.STRING, null, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - String[] rs = new String[keys.length]; - for (int i = 0; i < keys.length; i++) { - Object obj = list.get(i); - rs[i] = obj == null ? null : obj.toString(); - } - return rs; - }); - } - - @Override - public CompletableFuture> getStringMapAsync(String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.STRING, null, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - Map map = new LinkedHashMap<>(); - for (int i = 0; i < keys.length; i++) { - Object obj = list.get(i); - if (obj != null) map.put(keys[i], list.get(i)); - } - return map; - }); - } - - @Override - public CompletableFuture> getMapAsync(final Type componentType, String... keys) { - byte[][] bs = new byte[keys.length][]; - for (int i = 0; i < bs.length; i++) { - bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); - } - return (CompletableFuture) send("MGET", CacheEntryType.OBJECT, componentType, false, keys[0], bs).thenApply(r -> { - List list = (List) r; - Map map = new LinkedHashMap<>(); - for (int i = 0; i < keys.length; i++) { - Object obj = list.get(i); - if (obj != null) map.put(keys[i], list.get(i)); - } - return map; - }); - } - - @Override - public CompletableFuture>> getCollectionMapAsync(final boolean set, final Type componentType, final String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new HashMap<>(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - if (!set) { //list - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("LRANGE", CacheEntryType.OBJECT, componentType, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } else { - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("SMEMBERS", CacheEntryType.OBJECT, componentType, true, key, key.getBytes(StandardCharsets.UTF_8)).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - @Deprecated - public Collection getCollection(String key) { - return getCollectionAsync(key).join(); - } - - @Override - public Collection getCollection(String key, final Type componentType) { - return (Collection) getCollectionAsync(key, componentType).join(); - } - - @Override - public Map getLongMap(final String... keys) { - return getLongMapAsync(keys).join(); - } - - @Override - public Long[] getLongArray(final String... keys) { - return getLongArrayAsync(keys).join(); - } - - @Override - public Map getStringMap(final String... keys) { - return getStringMapAsync(keys).join(); - } - - @Override - public String[] getStringArray(final String... keys) { - return getStringArrayAsync(keys).join(); - } - - @Override - public Map getMap(final Type componentType, final String... keys) { - return (Map) getMapAsync(componentType, keys).join(); - } - - @Override - public Map> getCollectionMap(final boolean set, final Type componentType, String... keys) { - return (Map) getCollectionMapAsync(set, componentType, keys).join(); - } - - @Override - public CompletableFuture> getStringCollectionAsync(String key) { - return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(null); - if (new String((byte[]) t).contains("list")) { //list - return send("LRANGE", CacheEntryType.STRING, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}); - } else { - return send("SMEMBERS", CacheEntryType.STRING, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public CompletableFuture>> getStringCollectionMapAsync(final boolean set, String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new HashMap<>(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - if (!set) { //list - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("LRANGE", CacheEntryType.STRING, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } else { - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("SMEMBERS", CacheEntryType.STRING, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - public Collection getStringCollection(String key) { - return getStringCollectionAsync(key).join(); - } - - @Override - public Map> getStringCollectionMap(final boolean set, String... keys) { - return getStringCollectionMapAsync(set, keys).join(); - } - - @Override - public CompletableFuture> getLongCollectionAsync(String key) { - return (CompletableFuture) send("TYPE", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { - if (t == null) return CompletableFuture.completedFuture(null); - if (new String((byte[]) t).contains("list")) { //list - return send("LRANGE", CacheEntryType.LONG, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}); - } else { - return send("SMEMBERS", CacheEntryType.LONG, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)); - } - }); - } - - @Override - public CompletableFuture>> getLongCollectionMapAsync(final boolean set, String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new HashMap<>(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - if (!set) { //list - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("LRANGE", CacheEntryType.LONG, (Type) null, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } else { - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = send("SMEMBERS", CacheEntryType.LONG, (Type) null, true, key, key.getBytes(StandardCharsets.UTF_8)).thenAccept(c -> { - if (c != null) { - synchronized (map) { - map.put(key, (Collection) c); - } - } - }); - } - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - public Collection getLongCollection(String key) { - return getLongCollectionAsync(key).join(); - } - - @Override - public Map> getLongCollectionMap(final boolean set, String... keys) { - return getLongCollectionMapAsync(set, keys).join(); - } - - //--------------------- getCollectionAndRefresh ------------------------------ - @Override - @Deprecated - public CompletableFuture> getCollectionAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getCollectionAsync(key)); - } - - @Override - public CompletableFuture> getCollectionAndRefreshAsync(String key, int expireSeconds, final Type componentType) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getCollectionAsync(key, componentType)); - } - - @Override - @Deprecated - public Collection getCollectionAndRefresh(String key, final int expireSeconds) { - return getCollectionAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public Collection getCollectionAndRefresh(String key, final int expireSeconds, final Type componentType) { - return (Collection) getCollectionAndRefreshAsync(key, expireSeconds, componentType).join(); - } - - @Override - public CompletableFuture> getStringCollectionAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getStringCollectionAsync(key)); - } - - @Override - public Collection getStringCollectionAndRefresh(String key, final int expireSeconds) { - return getStringCollectionAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public CompletableFuture> getLongCollectionAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getLongCollectionAsync(key)); - } - - @Override - public Collection getLongCollectionAndRefresh(String key, final int expireSeconds) { - return getLongCollectionAndRefreshAsync(key, expireSeconds).join(); - } - - //--------------------- existsItem ------------------------------ - @Override - @Deprecated - public boolean existsSetItem(String key, V value) { - return existsSetItemAsync(key, value).join(); - } - - @Override - public boolean existsSetItem(String key, final Type componentType, T value) { - return existsSetItemAsync(key, componentType, value).join(); - } - - @Override - @Deprecated - public CompletableFuture existsSetItemAsync(String key, V value) { - return (CompletableFuture) send("SISMEMBER", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture existsSetItemAsync(String key, final Type componentType, T value) { - return (CompletableFuture) send("SISMEMBER", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - public boolean existsStringSetItem(String key, String value) { - return existsStringSetItemAsync(key, value).join(); - } - - @Override - public CompletableFuture existsStringSetItemAsync(String key, String value) { - return (CompletableFuture) send("SISMEMBER", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public boolean existsLongSetItem(String key, long value) { - return existsLongSetItemAsync(key, value).join(); - } - - @Override - public CompletableFuture existsLongSetItemAsync(String key, long value) { - return (CompletableFuture) send("SISMEMBER", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - //--------------------- appendListItem ------------------------------ - @Override - @Deprecated - public CompletableFuture appendListItemAsync(String key, V value) { - return (CompletableFuture) send("RPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture appendListItemAsync(String key, final Type componentType, T value) { - return (CompletableFuture) send("RPUSH", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - @Deprecated - public void appendListItem(String key, V value) { - appendListItemAsync(key, value).join(); - } - - @Override - public void appendListItem(String key, final Type componentType, T value) { - appendListItemAsync(key, componentType, value).join(); - } - - @Override - public CompletableFuture appendStringListItemAsync(String key, String value) { - return (CompletableFuture) send("RPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public void appendStringListItem(String key, String value) { - appendStringListItemAsync(key, value).join(); - } - - @Override - public CompletableFuture appendLongListItemAsync(String key, long value) { - return (CompletableFuture) send("RPUSH", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public void appendLongListItem(String key, long value) { - appendLongListItemAsync(key, value).join(); - } - - //--------------------- removeListItem ------------------------------ - @Override - @Deprecated - public CompletableFuture removeListItemAsync(String key, V value) { - return (CompletableFuture) send("LREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture removeListItemAsync(String key, final Type componentType, T value) { - return (CompletableFuture) send("LREM", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - @Deprecated - public int removeListItem(String key, V value) { - return removeListItemAsync(key, value).join(); - } - - @Override - public int removeListItem(String key, final Type componentType, T value) { - return removeListItemAsync(key, componentType, value).join(); - } - - @Override - public CompletableFuture removeStringListItemAsync(String key, String value) { - return (CompletableFuture) send("LREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public int removeStringListItem(String key, String value) { - return removeStringListItemAsync(key, value).join(); - } - - @Override - public CompletableFuture removeLongListItemAsync(String key, long value) { - return (CompletableFuture) send("LREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public int removeLongListItem(String key, long value) { - return removeLongListItemAsync(key, value).join(); - } - - //--------------------- appendSetItem ------------------------------ - @Override - @Deprecated - public CompletableFuture appendSetItemAsync(String key, V value) { - return (CompletableFuture) send("SADD", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture appendSetItemAsync(String key, Type componentType, T value) { - return (CompletableFuture) send("SADD", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - public CompletableFuture spopSetItemAsync(String key, Type componentType) { - return (CompletableFuture) send("SPOP", CacheEntryType.OBJECT, componentType, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> spopSetItemAsync(String key, int count, Type componentType) { - return (CompletableFuture) send("SPOP", CacheEntryType.OBJECT, componentType, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture spopStringSetItemAsync(String key) { - return (CompletableFuture) send("SPOP", CacheEntryType.STRING, String.class, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> spopStringSetItemAsync(String key, int count) { - return (CompletableFuture) send("SPOP", CacheEntryType.STRING, String.class, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture spopLongSetItemAsync(String key) { - return (CompletableFuture) send("SPOP", CacheEntryType.LONG, long.class, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> spopLongSetItemAsync(String key, int count) { - return (CompletableFuture) send("SPOP", CacheEntryType.LONG, long.class, key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8)); - } - - @Override - @Deprecated - public void appendSetItem(String key, V value) { - appendSetItemAsync(key, value).join(); - } - - @Override - public void appendSetItem(String key, final Type componentType, T value) { - appendSetItemAsync(key, componentType, value).join(); - } - - @Override - public T spopSetItem(String key, final Type componentType) { - return (T) spopSetItemAsync(key, componentType).join(); - } - - @Override - public List spopSetItem(String key, int count, final Type componentType) { - return (List) spopSetItemAsync(key, count, componentType).join(); - } - - @Override - public String spopStringSetItem(String key) { - return spopStringSetItemAsync(key).join(); - } - - @Override - public List spopStringSetItem(String key, int count) { - return spopStringSetItemAsync(key, count).join(); - } - - @Override - public Long spopLongSetItem(String key) { - return spopLongSetItemAsync(key).join(); - } - - @Override - public List spopLongSetItem(String key, int count) { - return spopLongSetItemAsync(key, count).join(); - } - - @Override - public CompletableFuture appendStringSetItemAsync(String key, String value) { - return (CompletableFuture) send("SADD", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public void appendStringSetItem(String key, String value) { - appendStringSetItemAsync(key, value).join(); - } - - @Override - public CompletableFuture appendLongSetItemAsync(String key, long value) { - return (CompletableFuture) send("SADD", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public void appendLongSetItem(String key, long value) { - appendLongSetItemAsync(key, value).join(); - } - - //--------------------- removeSetItem ------------------------------ - @Override - @Deprecated - public CompletableFuture removeSetItemAsync(String key, V value) { - return (CompletableFuture) send("SREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, (Type) null, value)); - } - - @Override - public CompletableFuture removeSetItemAsync(String key, final Type componentType, T value) { - return (CompletableFuture) send("SREM", null, componentType, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.OBJECT, (Convert) null, componentType, value)); - } - - @Override - @Deprecated - public int removeSetItem(String key, V value) { - return removeSetItemAsync(key, value).join(); - } - - @Override - public int removeSetItem(String key, final Type componentType, T value) { - return removeSetItemAsync(key, componentType, value).join(); - } - - @Override - public CompletableFuture removeStringSetItemAsync(String key, String value) { - return (CompletableFuture) send("SREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.STRING, (Convert) null, (Type) null, value)); - } - - @Override - public int removeStringSetItem(String key, String value) { - return removeStringSetItemAsync(key, value).join(); - } - - @Override - public CompletableFuture removeLongSetItemAsync(String key, long value) { - return (CompletableFuture) send("SREM", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), formatValue(CacheEntryType.LONG, (Convert) null, (Type) null, value)); - } - - @Override - public int removeLongSetItem(String key, long value) { - return removeLongSetItemAsync(key, value).join(); - } - - //--------------------- queryKeys ------------------------------ - @Override - public List queryKeys() { - return queryKeysAsync().join(); - } - - @Override - public List queryKeysStartsWith(String startsWith) { - return queryKeysStartsWithAsync(startsWith).join(); - } - - @Override - public List queryKeysEndsWith(String endsWith) { - return queryKeysEndsWithAsync(endsWith).join(); - } - - @Override - public byte[] getBytes(final String key) { - return getBytesAsync(key).join(); - } - - @Override - public byte[] getBytesAndRefresh(final String key, final int expireSeconds) { - return getBytesAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public void setBytes(final String key, final byte[] value) { - setBytesAsync(key, value).join(); - } - - @Override - public void setBytes(final int expireSeconds, final String key, final byte[] value) { - setBytesAsync(expireSeconds, key, value).join(); - } - - @Override - public void setBytes(final String key, final Convert convert, final Type type, final T value) { - setBytesAsync(key, convert, type, value).join(); - } - - @Override - public void setBytes(final int expireSeconds, final String key, final Convert convert, final Type type, final T value) { - setBytesAsync(expireSeconds, key, convert, type, value).join(); - } - - @Override - public CompletableFuture getBytesAsync(final String key) { - return (CompletableFuture) send("GET", CacheEntryType.BYTES, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture getBytesAndRefreshAsync(final String key, final int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getBytesAsync(key)); - } - - @Override - public CompletableFuture setBytesAsync(final String key, final byte[] value) { - return (CompletableFuture) send("SET", CacheEntryType.BYTES, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), value); - - } - - @Override - public CompletableFuture setBytesAsync(final int expireSeconds, final String key, final byte[] value) { - return (CompletableFuture) setBytesAsync(key, value).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture setBytesAsync(final String key, final Convert convert, final Type type, final T value) { - return (CompletableFuture) send("SET", CacheEntryType.BYTES, (Type) null, key, key.getBytes(StandardCharsets.UTF_8), convert.convertToBytes(type, value)); - } - - @Override - public CompletableFuture setBytesAsync(final int expireSeconds, final String key, final Convert convert, final Type type, final T value) { - return (CompletableFuture) setBytesAsync(key, convert.convertToBytes(type, value)).thenCompose(v -> setExpireSecondsAsync(key, expireSeconds)); - } - - @Override - public CompletableFuture> queryKeysAsync() { - return (CompletableFuture) send("KEYS", null, (Type) null, "*", new byte[]{(byte) '*'}); - } - - @Override - public CompletableFuture> queryKeysStartsWithAsync(String startsWith) { - if (startsWith == null) return queryKeysAsync(); - String key = startsWith + "*"; - return (CompletableFuture) send("KEYS", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public CompletableFuture> queryKeysEndsWithAsync(String endsWith) { - if (endsWith == null) return queryKeysAsync(); - String key = "*" + endsWith; - return (CompletableFuture) send("KEYS", null, (Type) null, key, key.getBytes(StandardCharsets.UTF_8)); - } - - //--------------------- getKeySize ------------------------------ - @Override - public int getKeySize() { - return getKeySizeAsync().join(); - } - - @Override - public CompletableFuture getKeySizeAsync() { - return (CompletableFuture) send("DBSIZE", null, (Type) null, null); - } - - //--------------------- queryList ------------------------------ - @Override - public List> queryList() { - return queryListAsync().join(); - } - - @Override - public CompletableFuture>> queryListAsync() { - return CompletableFuture.completedFuture(new ArrayList<>()); //不返回数据 - } - - //--------------------- send ------------------------------ - private byte[] formatValue(CacheEntryType cacheType, Convert convert0, Type resultType, Object value) { - if (value == null) return "null".getBytes(StandardCharsets.UTF_8); - if (value instanceof byte[]) return (byte[]) value; - if (convert0 == null) convert0 = convert; - if (cacheType == CacheEntryType.MAP) { - if ((value instanceof CharSequence) || (value instanceof Number)) { - return String.valueOf(value).getBytes(StandardCharsets.UTF_8); - } - if (objValueType == String.class && !(value instanceof CharSequence)) resultType = value.getClass(); - return convert0.convertToBytes(resultType == null ? objValueType : resultType, value); - } - if (cacheType == CacheEntryType.LONG || cacheType == CacheEntryType.ATOMIC || value.getClass() == String.class) - return String.valueOf(value).getBytes(StandardCharsets.UTF_8); - if (cacheType == CacheEntryType.STRING) return convert0.convertToBytes(String.class, value); - return convert0.convertToBytes(resultType == null ? objValueType : resultType, value); - } - - protected CompletableFuture send(final String command, final CacheEntryType cacheType, final Type resultType, final String key, final byte[]... args) { - return send(command, cacheType, resultType, false, key, args); - } - - protected CompletableFuture send(final String command, final CacheEntryType cacheType, final Type resultType, final boolean set, final String key, final byte[]... args) { - return send(null, command, cacheType, resultType, set, key, args); - } - - private CompletableFuture send(final CompletionHandler callback, final String command, final CacheEntryType cacheType, final Type resultType, final boolean set, final String key, final byte[]... args) { - final BsonByteBufferWriter writer = new BsonByteBufferWriter(transport.getBufferSupplier()); - writer.writeTo(ASTERISK_BYTE); - writer.writeTo(String.valueOf(args.length + 1).getBytes(StandardCharsets.UTF_8)); - writer.writeTo((byte) '\r', (byte) '\n'); - writer.writeTo(DOLLAR_BYTE); - writer.writeTo(String.valueOf(command.length()).getBytes(StandardCharsets.UTF_8)); - writer.writeTo((byte) '\r', (byte) '\n'); - writer.writeTo(command.getBytes(StandardCharsets.UTF_8)); - writer.writeTo((byte) '\r', (byte) '\n'); - - for (final byte[] arg : args) { - writer.writeTo(DOLLAR_BYTE); - writer.writeTo(String.valueOf(arg.length).getBytes(StandardCharsets.UTF_8)); - writer.writeTo((byte) '\r', (byte) '\n'); - writer.writeTo(arg); - writer.writeTo((byte) '\r', (byte) '\n'); - } - - final ByteBuffer[] buffers = writer.toBuffers(); - - final CompletableFuture future = callback == null ? new CompletableFuture<>() : null; - CompletableFuture connFuture = this.transport.pollConnection(null); - if (passwords != null) { - connFuture = connFuture.thenCompose(conn -> { - if (conn.getSubobject() != null) return CompletableFuture.completedFuture(conn); - byte[] password = passwords.get(conn.getRemoteAddress()); - if (password == null) return CompletableFuture.completedFuture(conn); - CompletableFuture rs = auth(conn, password, command); - if (db > 0) { - rs = rs.thenCompose(conn2 -> { - if (conn2.getSubobject() != null) return CompletableFuture.completedFuture(conn2); - return selectdb(conn2, db, command); - }); - } - return rs; - }); - } else if (db > 0) { - connFuture = connFuture.thenCompose(conn2 -> { - if (conn2.getSubobject() != null) return CompletableFuture.completedFuture(conn2); - return selectdb(conn2, db, command); - }); - } - connFuture.whenComplete((conn, ex) -> { - if (ex != null) { - transport.offerBuffer(buffers); - if (future == null) { - callback.failed(ex, null); - } else { - future.completeExceptionally(ex); - } - return; - } - conn.write(buffers, buffers, new CompletionHandler() { - @Override - public void completed(Integer result, ByteBuffer[] attachments) { - int index = -1; - try { - for (int i = 0; i < attachments.length; i++) { - if (attachments[i].hasRemaining()) { - index = i; - break; - } else { - transport.offerBuffer(attachments[i]); - } - } - if (index == 0) { - conn.write(attachments, attachments, this); - return; - } else if (index > 0) { - ByteBuffer[] newattachs = new ByteBuffer[attachments.length - index]; - System.arraycopy(attachments, index, newattachs, 0, newattachs.length); - conn.write(newattachs, newattachs, this); - return; - } - //----------------------- 读取返回结果 ------------------------------------- - conn.read(new ReplyCompletionHandler(conn) { - @Override - public void completed(Integer result, ByteBuffer buffer) { - buffer.flip(); - try { - final byte sign = buffer.get(); - if (sign == PLUS_BYTE) { // + - byte[] bs = readBytes(buffer); - if (future == null) { - transport.offerConnection(false, conn); //必须在complete之前,防止并发是conn还没回收完毕 - callback.completed(null, key); - } else { - transport.offerConnection(false, conn); - future.complete(("SET".equals(command) || "HSET".equals(command)) ? null : bs); - } - } else if (sign == MINUS_BYTE) { // - - String bs = readString(buffer); - if (future == null) { - transport.offerConnection(false, conn); - callback.failed(new RuntimeException(bs), key); - } else { - transport.offerConnection(false, conn); - future.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } - } else if (sign == COLON_BYTE) { // : - long rs = readLong(buffer); - if (future == null) { - if (command.startsWith("INCR") || command.startsWith("DECR") || command.startsWith("HINCR")) { - transport.offerConnection(false, conn); - callback.completed(rs, key); - } else { - transport.offerConnection(false, conn); - callback.completed((command.endsWith("EXISTS") || "SISMEMBER".equals(command)) ? (rs > 0) : (("LLEN".equals(command) || "SCARD".equals(command) || "SREM".equals(command) || "LREM".equals(command) || "DEL".equals(command) || "HDEL".equals(command) || "HLEN".equals(command) || "DBSIZE".equals(command)) ? (int) rs : null), key); - } - } else { - if (command.startsWith("INCR") || command.startsWith("DECR") || command.startsWith("HINCR") || command.startsWith("HGET")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else if (command.equals("ZRANK") || command.equals("ZREVRANK")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else if (command.equals("GETBIT")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else if (command.equals("TTL") || command.equals("PTTL")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else if (command.equals("SETNX")) { - transport.offerConnection(false, conn); - future.complete(rs); - } else { - transport.offerConnection(false, conn); - future.complete((command.endsWith("EXISTS") || "SISMEMBER".equals(command)) ? (rs > 0) : (("LLEN".equals(command) || "SCARD".equals(command) || "SREM".equals(command) || "LREM".equals(command) || "DEL".equals(command) || "HDEL".equals(command) || "HLEN".equals(command) || "DBSIZE".equals(command) || "ZCARD".equals(command) || "EVAL".equals(command)) ? (int) rs : null)); - } - } - } else if (sign == DOLLAR_BYTE) { // $ - long val = readLong(buffer); - byte[] rs = val <= 0 ? null : readBytes(buffer); - Type ct = cacheType == CacheEntryType.LONG ? long.class : (cacheType == CacheEntryType.STRING ? String.class : (resultType == null ? objValueType : resultType)); - if (future == null) { - transport.offerConnection(false, conn); - callback.completed((("SPOP".equals(command) || command.endsWith("GET") || rs == null) ? (ct == String.class && rs != null ? new String(rs, StandardCharsets.UTF_8) : convert.convertFrom(ct, new String(rs, StandardCharsets.UTF_8))) : null), key); - } else { - transport.offerConnection(false, conn); - if ("ZSCORE".equals(command)) { - future.complete(ct == String.class && rs != null ? new String(rs, StandardCharsets.UTF_8) : convert.convertFrom(ct, rs == null ? null : new String(rs, StandardCharsets.UTF_8))); - } else if (command.equals("HINCRBYFLOAT")) { - future.complete(new String(rs, StandardCharsets.UTF_8)); - } else { - future.complete("SPOP".equals(command) || command.endsWith("GET") || command.endsWith("ZINCRBY") ? (ct == String.class && rs != null ? new String(rs, StandardCharsets.UTF_8) : convert.convertFrom(ct, rs == null ? null : new String(rs, StandardCharsets.UTF_8))) : rs); - } - } - } else if (sign == ASTERISK_BYTE) { // * - final int len = readInt(buffer); - if (len < 0) { - if (future == null) { - transport.offerConnection(false, conn); - callback.completed(null, key); - } else { - transport.offerConnection(false, conn); - future.complete((byte[]) null); - } - } else { - Object rsobj; - if (command.endsWith("SCAN")) { - LinkedHashMap rs = new LinkedHashMap(); - rsobj = rs; - for (int i = 0; i < len; i++) { - int l = readInt(buffer); - if (l > 0) { - readBytes(buffer); - } else { - while (buffer.hasRemaining()) { - readBytes(buffer); - String field = new String(readBytes(buffer), StandardCharsets.UTF_8); - String value = null; - if (readInt(buffer) > 0) { - value = new String(readBytes(buffer), StandardCharsets.UTF_8); - } - Type ct = cacheType == CacheEntryType.LONG ? long.class : (cacheType == CacheEntryType.STRING ? String.class : (resultType == null ? objValueType : resultType)); - try { - rs.put(field, value == null ? null : (ct == String.class ? value : convert.convertFrom(ct, value))); - } catch (RuntimeException e) { - buffer.flip(); - byte[] bsss = new byte[buffer.remaining()]; - buffer.get(bsss); - logger.log(Level.SEVERE, "异常: " + new String(bsss)); - throw e; - } - } - } - } - } else { - Collection rs = set ? new HashSet() : new ArrayList(); - rsobj = rs; - boolean keys = "KEYS".equals(command) || "HKEYS".equals(command); - boolean mget = !keys && ("MGET".equals(command) || "HMGET".equals(command)); - boolean zsetscore = !keys && ("ZREVRANGE".equals(command) || "ZRANGE".equals(command)); - boolean hgetall = !keys && "HGETALL".equals(command); - boolean lpop = !keys && "BRPOP".equals(command); - Type ct = cacheType == CacheEntryType.LONG ? long.class : (cacheType == CacheEntryType.STRING ? String.class : (resultType == null ? objValueType : resultType)); - for (int i = 0; i < len; i++) { - int l = readInt(buffer); - if (l > 0) { - // 1、zsetscore 查询 偶数元素统一返回 string 方法内自定义转换 - // 2、hgetall 基数元素返回 string - if ((zsetscore && rs.size() % 2 == 1) || (hgetall && rs.size() % 2 == 0)) { - rs.add(readString(buffer)); - } else if (lpop && i == 1) { - rsobj = convert.convertFrom(ct, new String(readBytes(buffer), StandardCharsets.UTF_8)); - } else { - rs.add(keys ? new String(readBytes(buffer), StandardCharsets.UTF_8) : (ct == String.class ? new String(readBytes(buffer), StandardCharsets.UTF_8) : convert.convertFrom(ct, new String(readBytes(buffer), StandardCharsets.UTF_8)))); - } - } else if (mget) { - rs.add(null); - } - } - } - if (future == null) { - transport.offerConnection(false, conn); - callback.completed(rsobj, key); - } else { - transport.offerConnection(false, conn); - future.complete((Serializable) rsobj); - } - } - } else { - String exstr = "Unknown reply: " + (char) sign; - if (future == null) { - transport.offerConnection(false, conn); - callback.failed(new RuntimeException(exstr), key); - } else { - transport.offerConnection(false, conn); - future.completeExceptionally(new RuntimeException(exstr)); - } - } - } catch (Exception e) { - logger.log(Level.WARNING, "", e); - failed(e, buffer); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer attachment) { - conn.offerBuffer(attachment); - transport.offerConnection(true, conn); - if (future == null) { - callback.failed(exc, attachments); - } else { - future.completeExceptionally(exc); - } - } - - }); - } catch (Exception e) { - failed(e, attachments); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer[] attachments) { - transport.offerConnection(true, conn); - if (future == null) { - callback.failed(exc, attachments); - } else { - future.completeExceptionally(exc); - } - } - }); - }); - return future; //.orTimeout(3, TimeUnit.SECONDS) JDK9以上才支持 - } - - private CompletableFuture selectdb(final AsyncConnection conn, final int db, final String command) { - final CompletableFuture rsfuture = new CompletableFuture(); - try { - final BsonByteBufferWriter dbwriter = new BsonByteBufferWriter(transport.getBufferSupplier()); - dbwriter.writeTo(ASTERISK_BYTE); - dbwriter.writeTo((byte) '2'); - dbwriter.writeTo((byte) '\r', (byte) '\n'); - dbwriter.writeTo(DOLLAR_BYTE); - dbwriter.writeTo((byte) '6'); - dbwriter.writeTo((byte) '\r', (byte) '\n'); - dbwriter.writeTo("SELECT".getBytes(StandardCharsets.UTF_8)); - dbwriter.writeTo((byte) '\r', (byte) '\n'); - - dbwriter.writeTo(DOLLAR_BYTE); - dbwriter.writeTo(String.valueOf(String.valueOf(db).length()).getBytes(StandardCharsets.UTF_8)); - dbwriter.writeTo((byte) '\r', (byte) '\n'); - dbwriter.writeTo(String.valueOf(db).getBytes(StandardCharsets.UTF_8)); - dbwriter.writeTo((byte) '\r', (byte) '\n'); - - final ByteBuffer[] authbuffers = dbwriter.toBuffers(); - conn.write(authbuffers, authbuffers, new CompletionHandler() { - @Override - public void completed(Integer result, ByteBuffer[] attachments) { - int index = -1; - try { - for (int i = 0; i < attachments.length; i++) { - if (attachments[i].hasRemaining()) { - index = i; - break; - } else { - transport.offerBuffer(attachments[i]); - } - } - if (index == 0) { - conn.write(attachments, attachments, this); - return; - } else if (index > 0) { - ByteBuffer[] newattachs = new ByteBuffer[attachments.length - index]; - System.arraycopy(attachments, index, newattachs, 0, newattachs.length); - conn.write(newattachs, newattachs, this); - return; - } - //----------------------- 读取返回结果 ------------------------------------- - conn.read(new ReplyCompletionHandler(conn) { - @Override - public void completed(Integer result, ByteBuffer buffer) { - buffer.flip(); - try { - final byte sign = buffer.get(); - if (sign == PLUS_BYTE) { // + - byte[] bs = readBytes(buffer); - if ("OK".equalsIgnoreCase(new String(bs))) { - conn.setSubobject("authed+db"); - rsfuture.complete(conn); - } else { - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } - } else if (sign == MINUS_BYTE) { // - 异常 - String bs = readString(buffer); - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } else { - String exstr = "Unknown reply: " + (char) sign; - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException(exstr)); - } - } catch (Exception e) { - failed(e, buffer); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer buffer) { - conn.offerBuffer(buffer); - transport.offerConnection(true, conn); - rsfuture.completeExceptionally(exc); - } - - }); - } catch (Exception e) { - failed(e, attachments); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer[] attachments) { - transport.offerConnection(true, conn); - rsfuture.completeExceptionally(exc); - } - }); - } catch (Exception e) { - rsfuture.completeExceptionally(e); - } - return rsfuture; - } - - private CompletableFuture auth(final AsyncConnection conn, final byte[] password, final String command) { - final CompletableFuture rsfuture = new CompletableFuture(); - try { - final BsonByteBufferWriter authwriter = new BsonByteBufferWriter(transport.getBufferSupplier()); - authwriter.writeTo(ASTERISK_BYTE); - authwriter.writeTo((byte) '2'); - authwriter.writeTo((byte) '\r', (byte) '\n'); - authwriter.writeTo(DOLLAR_BYTE); - authwriter.writeTo((byte) '4'); - authwriter.writeTo((byte) '\r', (byte) '\n'); - authwriter.writeTo("AUTH".getBytes(StandardCharsets.UTF_8)); - authwriter.writeTo((byte) '\r', (byte) '\n'); - - authwriter.writeTo(DOLLAR_BYTE); - authwriter.writeTo(String.valueOf(password.length).getBytes(StandardCharsets.UTF_8)); - authwriter.writeTo((byte) '\r', (byte) '\n'); - authwriter.writeTo(password); - authwriter.writeTo((byte) '\r', (byte) '\n'); - - final ByteBuffer[] authbuffers = authwriter.toBuffers(); - conn.write(authbuffers, authbuffers, new CompletionHandler() { - @Override - public void completed(Integer result, ByteBuffer[] attachments) { - int index = -1; - try { - for (int i = 0; i < attachments.length; i++) { - if (attachments[i].hasRemaining()) { - index = i; - break; - } else { - transport.offerBuffer(attachments[i]); - } - } - if (index == 0) { - conn.write(attachments, attachments, this); - return; - } else if (index > 0) { - ByteBuffer[] newattachs = new ByteBuffer[attachments.length - index]; - System.arraycopy(attachments, index, newattachs, 0, newattachs.length); - conn.write(newattachs, newattachs, this); - return; - } - //----------------------- 读取返回结果 ------------------------------------- - conn.read(new ReplyCompletionHandler(conn) { - @Override - public void completed(Integer result, ByteBuffer buffer) { - buffer.flip(); - try { - final byte sign = buffer.get(); - if (sign == PLUS_BYTE) { // + - byte[] bs = readBytes(buffer); - if ("OK".equalsIgnoreCase(new String(bs))) { - conn.setSubobject("authed"); - rsfuture.complete(conn); - } else { - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } - } else if (sign == MINUS_BYTE) { // - 异常 - String bs = readString(buffer); - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException("command : " + command + ", error: " + bs)); - } else { - String exstr = "Unknown reply: " + (char) sign; - transport.offerConnection(false, conn); - rsfuture.completeExceptionally(new RuntimeException(exstr)); - } - } catch (Exception e) { - failed(e, buffer); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer buffer) { - conn.offerBuffer(buffer); - transport.offerConnection(true, conn); - rsfuture.completeExceptionally(exc); - } - - }); - } catch (Exception e) { - failed(e, attachments); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer[] attachments) { - transport.offerConnection(true, conn); - rsfuture.completeExceptionally(exc); - } - }); - } catch (Exception e) { - rsfuture.completeExceptionally(e); - } - return rsfuture; - } -} - -abstract class ReplyCompletionHandler implements CompletionHandler { - - private final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - protected final ByteArray out = new ByteArray(); - - protected final AsyncConnection conn; - - public ReplyCompletionHandler(AsyncConnection conn) { - this.conn = conn; - } - - protected byte[] readBytes(ByteBuffer buffer) throws IOException { - readLine(buffer); - return out.getBytesAndClear(); - } - - protected String readString(ByteBuffer buffer) throws IOException { - readLine(buffer); - return out.toStringAndClear(null);//传null则表示使用StandardCharsets.UTF_8 - } - - protected int readInt(ByteBuffer buffer) throws IOException { - return (int) readLong(buffer); - } - - protected long readLong(ByteBuffer buffer) throws IOException { - readLine(buffer); - int start = 0; - if (out.get(0) == '$') start = 1; - boolean negative = out.get(start) == '-'; - long value = negative ? 0 : (out.get(start) - '0'); - for (int i = 1 + start; i < out.size(); i++) { - value = value * 10 + (out.get(i) - '0'); - } - out.clear(); - return negative ? -value : value; - } - - private void readLine(ByteBuffer buffer) throws IOException { - boolean has = buffer.hasRemaining(); - byte lasted = has ? buffer.get() : 0; - if (lasted == '\n' && !out.isEmpty() && out.getLastByte() == '\r') { - out.removeLastByte();//读掉 \r - //buffer.get();//读掉 \n - //logger.info("打印buffer.get()---> " + buffer.get()); - //logger.info("--- 打印buffer start --- "); - return;//传null则表示使用StandardCharsets.UTF_8 - } - if (has) out.write(lasted); - while (buffer.hasRemaining()) { - byte b = buffer.get(); - if (b == '\n' && lasted == '\r') { - out.removeLastByte(); - return; - } - out.write(lasted = b); - } - //说明数据还没读取完 - buffer.clear(); - conn.readableByteChannel().read(buffer); - buffer.flip(); - readLine(buffer); - } - -} diff --git a/src/com/zdemo/cachex/RedissionCacheSource.java b/src/com/zdemo/cachex/RedissionCacheSource.java deleted file mode 100644 index 59e0b9d..0000000 --- a/src/com/zdemo/cachex/RedissionCacheSource.java +++ /dev/null @@ -1,1944 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - *//* - -package org.redkalex.cache; - -import java.io.*; -import java.lang.reflect.Type; -import java.net.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.logging.*; -import java.util.stream.Collectors; -import javax.annotation.Resource; -import org.redisson.Redisson; -import org.redisson.api.*; -import org.redisson.config.*; -import org.redkale.convert.Convert; -import org.redkale.convert.json.*; -import org.redkale.convert.json.JsonConvert; -import org.redkale.service.*; -import org.redkale.source.*; -import org.redkale.util.*; -import org.redkale.util.AnyValue.DefaultAnyValue; - -*/ -/** - * //https://www.cnblogs.com/xiami2046/p/13934146.html - * - * @author zhangjx - *//* - -@Local -@AutoLoad(false) -@ResourceType(CacheSource.class) -public class RedissionCacheSource extends AbstractService implements CacheSource, Service, AutoCloseable, Resourcable { - - private final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - - @Resource - protected JsonConvert defaultConvert; - - @Resource(name = "$_convert") - protected JsonConvert convert; - - protected Type objValueType = String.class; - - protected List nodeAddrs; - - protected int db; - - protected RedissonClient redisson; - - @Override - public void init(AnyValue conf) { - if (this.convert == null) this.convert = this.defaultConvert; - if (conf == null) conf = new AnyValue.DefaultAnyValue(); - - final List addresses = new ArrayList<>(); - Config config = new Config(); - AnyValue[] nodes = conf.getAnyValues("node"); - String type = conf.getOrDefault("type", ""); - BaseConfig baseConfig = null; - for (AnyValue node : nodes) { - String addr = node.getValue("addr"); - addresses.add(addr); - String db0 = node.getValue("db", "").trim(); - if (!db0.isEmpty()) this.db = Integer.valueOf(db0); - if (nodes.length == 1) { - baseConfig = config.useSingleServer(); - config.useSingleServer().setAddress(addr); - config.useSingleServer().setDatabase(this.db); - } else if ("masterslave".equalsIgnoreCase(type)) { //主从 - baseConfig = config.useMasterSlaveServers(); - if (node.get("master") != null) { - config.useMasterSlaveServers().setMasterAddress(addr); - } else { - config.useMasterSlaveServers().addSlaveAddress(addr); - } - config.useMasterSlaveServers().setDatabase(this.db); - } else if ("cluster".equalsIgnoreCase(type)) { //集群 - baseConfig = config.useClusterServers(); - config.useClusterServers().addNodeAddress(addr); - } else if ("replicated".equalsIgnoreCase(type)) { // - baseConfig = config.useReplicatedServers(); - config.useReplicatedServers().addNodeAddress(addr); - config.useReplicatedServers().setDatabase(this.db); - } else if ("sentinel".equalsIgnoreCase(type)) { // - baseConfig = config.useSentinelServers(); - config.useSentinelServers().addSentinelAddress(addr); - config.useSentinelServers().setDatabase(this.db); - } - } - if (baseConfig != null) { - String username = conf.getValue("username", "").trim(); - String password = conf.getValue("password", "").trim(); - String retryAttempts = conf.getValue("retryAttempts", "").trim(); - String retryInterval = conf.getValue("retryInterval", "").trim(); - if (!username.isEmpty()) baseConfig.setUsername(username); - if (!password.isEmpty()) baseConfig.setPassword(password); - if (!retryAttempts.isEmpty()) baseConfig.setRetryAttempts(Integer.parseInt(retryAttempts)); - if (!retryInterval.isEmpty()) baseConfig.setRetryInterval(Integer.parseInt(retryInterval)); - } - this.redisson = Redisson.create(config); - this.nodeAddrs = addresses; - if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, RedisCacheSource.class.getSimpleName() + ": addrs=" + addresses + ", db=" + db); - - } - - @Override //ServiceLoader时判断配置是否符合当前实现类 - public boolean match(AnyValue config) { - if (config == null) return false; - AnyValue[] nodes = config.getAnyValues("node"); - if (nodes == null || nodes.length == 0) return false; - for (AnyValue node : nodes) { - String val = node.getValue("addr"); - if (val != null && val.startsWith("redis://")) return true; - } - return false; - } - - @Override - @Deprecated - public final void initValueType(Type valueType) { - this.objValueType = valueType == null ? String.class : valueType; - } - - @Override - @Deprecated - public final void initTransient(boolean flag) { - } - - @Override - public final String getType() { - return "redis"; - } - - protected CompletableFuture completableFuture(CompletionStage rf) { - CompletableFuture future = new CompletableFuture(); - rf.whenComplete((r, t) -> { - if (t != null) { - future.completeExceptionally(t); - } else { - future.complete(r); - } - }); - return future; - } - - public static void main(String[] args) throws Exception { - DefaultAnyValue conf = new DefaultAnyValue().addValue("maxconns", "1"); - conf.addValue("node", new DefaultAnyValue().addValue("addr", "redis://127.0.0.1:6363")); - - RedissionCacheSource source = new RedissionCacheSource(); - source.defaultConvert = JsonFactory.root().getConvert(); - source.init(conf); - InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 7788); - try { - System.out.println("------------------------------------"); - source.removeAsync("stritem1"); - source.removeAsync("stritem2"); - source.setStringAsync("stritem1", "value1"); - source.setStringAsync("stritem2", "value2"); - System.out.println("stritem开头的key有两个: " + source.queryKeysStartsWith("stritem")); - System.out.println("[有值] MGET : " + source.getStringMap("stritem1", "stritem2")); - System.out.println("[有值] MGET : " + Arrays.toString(source.getStringArray("stritem1", "stritem2"))); - - source.remove("intitem1"); - source.remove("intitem2"); - source.setLong("intitem1", 333); - source.setLong("intitem2", 444); - System.out.println("[有值] MGET : " + source.getStringMap("intitem1", "intitem22", "intitem2")); - System.out.println("[有值] MGET : " + Arrays.toString(source.getStringArray("intitem1", "intitem22", "intitem2"))); - source.remove("objitem1"); - source.remove("objitem2"); - source.set("objitem1", Flipper.class, new Flipper(10)); - source.set("objitem2", Flipper.class, new Flipper(20)); - System.out.println("[有值] MGET : " + source.getMap(Flipper.class, "objitem1", "objitem2")); - - source.remove("key1"); - source.remove("key2"); - source.remove("300"); - source.set(1000, "key1", String.class, "value1"); - source.set("key1", String.class, "value1"); - source.setString("keystr1", "strvalue1"); - source.setLong("keylong1", 333L); - source.set("300", String.class, "4000"); - source.getAndRefresh("key1", 3500, String.class); - System.out.println("[有值] 300 GET : " + source.get("300", String.class)); - System.out.println("[有值] key1 GET : " + source.get("key1", String.class)); - System.out.println("[无值] key2 GET : " + source.get("key2", String.class)); - System.out.println("[有值] keystr1 GET : " + source.getString("keystr1")); - System.out.println("[有值] keylong1 GET : " + source.getLong("keylong1", 0L)); - System.out.println("[有值] key1 EXISTS : " + source.exists("key1")); - System.out.println("[无值] key2 EXISTS : " + source.exists("key2")); - - source.remove("keys3"); - source.appendListItem("keys3", String.class, "vals1"); - source.appendListItem("keys3", String.class, "vals2"); - System.out.println("-------- keys3 追加了两个值 --------"); - System.out.println("[两值] keys3 VALUES : " + source.getCollection("keys3", String.class)); - System.out.println("[有值] keys3 EXISTS : " + source.exists("keys3")); - source.removeListItem("keys3", String.class, "vals1"); - System.out.println("[一值] keys3 VALUES : " + source.getCollection("keys3", String.class)); - source.getCollectionAndRefresh("keys3", 3000, String.class); - - source.remove("stringmap"); - source.appendSetItem("stringmap", JsonConvert.TYPE_MAP_STRING_STRING, Utility.ofMap("a", "aa", "b", "bb")); - source.appendSetItem("stringmap", JsonConvert.TYPE_MAP_STRING_STRING, Utility.ofMap("c", "cc", "d", "dd")); - System.out.println("[两值] stringmap VALUES : " + source.getCollectionAsync("stringmap", JsonConvert.TYPE_MAP_STRING_STRING).join()); - - source.remove("sets3"); - source.remove("sets4"); - source.appendSetItem("sets3", String.class, "setvals1"); - source.appendSetItem("sets3", String.class, "setvals2"); - source.appendSetItem("sets3", String.class, "setvals1"); - source.appendSetItem("sets4", String.class, "setvals2"); - source.appendSetItem("sets4", String.class, "setvals1"); - System.out.println("[两值] sets3 VALUES : " + source.getCollection("sets3", String.class)); - System.out.println("[有值] sets3 EXISTS : " + source.exists("sets3")); - System.out.println("[有值] sets3-setvals2 EXISTSITEM : " + source.existsSetItem("sets3", String.class, "setvals2")); - System.out.println("[有值] sets3-setvals3 EXISTSITEM : " + source.existsSetItem("sets3", String.class, "setvals3")); - source.removeSetItem("sets3", String.class, "setvals1"); - System.out.println("[一值] sets3 VALUES : " + source.getCollection("sets3", String.class)); - System.out.println("sets3 大小 : " + source.getCollectionSize("sets3")); - System.out.println("all keys: " + source.queryKeys()); - System.out.println("key startkeys: " + source.queryKeysStartsWith("key")); - System.out.println("newnum 值 : " + source.incr("newnum")); - System.out.println("newnum 值 : " + source.decr("newnum")); - System.out.println("sets3&sets4: " + source.getStringCollectionMap(true, "sets3", "sets4")); - System.out.println("------------------------------------"); - source.set("myaddr", InetSocketAddress.class, addr); - System.out.println("myaddrstr: " + source.getString("myaddr")); - System.out.println("myaddr: " + source.get("myaddr", InetSocketAddress.class)); - source.remove("myaddrs"); - source.remove("myaddrs2"); - source.appendSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788)); - source.appendSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7799)); - System.out.println("myaddrs: " + source.getCollection("myaddrs", InetSocketAddress.class)); - source.removeSetItem("myaddrs", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788)); - System.out.println("myaddrs: " + source.getCollection("myaddrs", InetSocketAddress.class)); - source.appendSetItem("myaddrs2", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7788)); - source.appendSetItem("myaddrs2", InetSocketAddress.class, new InetSocketAddress("127.0.0.1", 7799)); - System.out.println("myaddrs&myaddrs2: " + source.getCollectionMap(true, InetSocketAddress.class, "myaddrs", "myaddrs2")); - System.out.println("------------------------------------"); - source.remove("myaddrs"); - Type mapType = new TypeToken>() { - }.getType(); - Map map = new HashMap<>(); - map.put("a", 1); - map.put("b", 2); - source.set("mapvals", mapType, map); - System.out.println("mapvals: " + source.get("mapvals", mapType)); - - source.remove("byteskey"); - source.setBytes("byteskey", new byte[]{1, 2, 3}); - System.out.println("byteskey 值 : " + Arrays.toString(source.getBytes("byteskey"))); - //h - source.remove("hmap"); - source.hincr("hmap", "key1"); - System.out.println("hmap.key1 值 : " + source.hgetLong("hmap", "key1", -1)); - source.hmset("hmap", "key2", "haha", "key3", 333); - source.hmset("hmap", "sm", (HashMap) Utility.ofMap("a", "aa", "b", "bb")); - System.out.println("hmap.sm 值 : " + source.hget("hmap", "sm", JsonConvert.TYPE_MAP_STRING_STRING)); - System.out.println("hmap.[key1,key2,key3] 值 : " + source.hmget("hmap", String.class, "key1", "key2", "key3")); - System.out.println("hmap.keys 四值 : " + source.hkeys("hmap")); - source.hremove("hmap", "key1", "key3"); - System.out.println("hmap.keys 两值 : " + source.hkeys("hmap")); - System.out.println("hmap.key2 值 : " + source.hgetString("hmap", "key2")); - System.out.println("hmap列表(2)大小 : " + source.hsize("hmap")); - - source.remove("hmaplong"); - source.hincr("hmaplong", "key1", 10); - source.hsetLong("hmaplong", "key2", 30); - System.out.println("hmaplong.所有两值 : " + source.hmap("hmaplong", long.class, 0, 10)); - - source.remove("hmapstr"); - source.hsetString("hmapstr", "key1", "str10"); - source.hsetString("hmapstr", "key2", null); - System.out.println("hmapstr.所有一值 : " + source.hmap("hmapstr", String.class, 0, 10)); - - source.remove("hmapstrmap"); - source.hset("hmapstrmap", "key1", JsonConvert.TYPE_MAP_STRING_STRING, (HashMap) Utility.ofMap("ks11", "vv11")); - source.hset("hmapstrmap", "key2", JsonConvert.TYPE_MAP_STRING_STRING, null); - System.out.println("hmapstrmap.无值 : " + source.hmap("hmapstrmap", JsonConvert.TYPE_MAP_STRING_STRING, 0, 10, "key2*")); - - source.remove("popset"); - source.appendStringSetItem("popset", "111"); - source.appendStringSetItem("popset", "222"); - source.appendStringSetItem("popset", "333"); - source.appendStringSetItem("popset", "444"); - source.appendStringSetItem("popset", "555"); - System.out.println("SPOP一个元素:" + source.spopStringSetItem("popset")); - System.out.println("SPOP两个元素:" + source.spopStringSetItem("popset", 2)); - System.out.println("SPOP五个元素:" + source.spopStringSetItem("popset", 5)); - source.appendLongSetItem("popset", 111); - source.appendLongSetItem("popset", 222); - source.appendLongSetItem("popset", 333); - source.appendLongSetItem("popset", 444); - source.appendLongSetItem("popset", 555); - System.out.println("SPOP一个元素:" + source.spopLongSetItem("popset")); - System.out.println("SPOP两个元素:" + source.spopLongSetItem("popset", 2)); - System.out.println("SPOP五个元素:" + source.spopLongSetItem("popset", 5)); - System.out.println("SPOP一个元素:" + source.spopLongSetItem("popset")); - - //清除 - int rs = source.remove("stritem1"); - System.out.println("删除stritem1个数: " + rs); - source.remove("popset"); - source.remove("stritem2"); - source.remove("intitem1"); - source.remove("intitem2"); - source.remove("keylong1"); - source.remove("keystr1"); - source.remove("mapvals"); - source.remove("myaddr"); - source.remove("myaddrs2"); - source.remove("newnum"); - source.remove("objitem1"); - source.remove("objitem2"); - source.remove("key1"); - source.remove("key2"); - source.remove("keys3"); - source.remove("sets3"); - source.remove("sets4"); - source.remove("myaddrs"); - source.remove("300"); - source.remove("stringmap"); - source.remove("hmap"); - source.remove("hmaplong"); - source.remove("hmapstr"); - source.remove("hmapstrmap"); - source.remove("byteskey"); - System.out.println("------------------------------------"); -// System.out.println("--------------测试大文本---------------"); -// HashMap bigmap = new HashMap<>(); -// StringBuilder sb = new StringBuilder(); -// sb.append("起始"); -// for (int i = 0; i < 1024 * 1024; i++) { -// sb.append("abcde"); -// } -// sb.append("结束"); -// bigmap.put("val", sb.toString()); -// System.out.println("文本长度: " + sb.length()); -// source.set("bigmap", JsonConvert.TYPE_MAP_STRING_STRING, bigmap); -// System.out.println("写入完成"); -// for (int i = 0; i < 1; i++) { -// HashMap fs = (HashMap) source.get("bigmap", JsonConvert.TYPE_MAP_STRING_STRING); -// System.out.println("内容长度: " + fs.get("val").length()); -// } - source.remove("bigmap"); - - } finally { - source.close(); - } - } - - @Override - public void close() throws Exception { //在 Application 关闭时调用 - destroy(null); - } - - @Override - public String resourceName() { - Resource res = this.getClass().getAnnotation(Resource.class); - return res == null ? "" : res.name(); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{addrs = " + this.nodeAddrs + ", db=" + this.db + "}"; - } - - @Override - public void destroy(AnyValue conf) { - if (redisson != null) redisson.shutdown(); - } - - //--------------------- exists ------------------------------ - @Override - public CompletableFuture existsAsync(String key) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.isExistsAsync()); - } - - @Override - public boolean exists(String key) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return bucket.isExists(); - } - - //--------------------- get ------------------------------ - @Override - @Deprecated - public CompletableFuture getAsync(String key) { - return getAsync(key, objValueType); - } - - @Override - public CompletableFuture getAsync(String key, Type type) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.getAsync().thenApply(bs -> bs == null ? null : convert.convertFrom(type, bs))); - } - - @Override - public CompletableFuture getStringAsync(String key) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.StringCodec.INSTANCE); - return completableFuture(bucket.getAsync()); - } - - @Override - public CompletableFuture getLongAsync(String key, long defValue) { - final RAtomicLong bucket = redisson.getAtomicLong(key); - return completableFuture(bucket.getAsync()); - } - - @Override - @Deprecated - public V get(String key) { - return get(key, objValueType); - } - - @Override - public T get(String key, final Type type) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - byte[] bs = bucket.get(); - return bs == null ? null : convert.convertFrom(type, bs); - } - - @Override - public String getString(String key) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.StringCodec.INSTANCE); - return bucket.get(); - } - - @Override - public long getLong(String key, long defValue) { - final RAtomicLong bucket = redisson.getAtomicLong(key); - return bucket.get(); - } - - //--------------------- getAndRefresh ------------------------------ - @Override - @Deprecated - public CompletableFuture getAndRefreshAsync(String key, int expireSeconds) { - return getAndRefreshAsync(key, expireSeconds, objValueType); - } - - @Override - public CompletableFuture getAndRefreshAsync(String key, int expireSeconds, final Type type) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.getAsync().thenCompose(bs -> { - T rs = convert.convertFrom(type, bs); - if (rs == null) return CompletableFuture.completedFuture(null); - return bucket.expireAsync(expireSeconds, TimeUnit.SECONDS).thenApply(v -> rs); - })); - } - - @Override - @Deprecated - public V getAndRefresh(String key, final int expireSeconds) { - return getAndRefresh(key, expireSeconds, objValueType); - } - - @Override - public T getAndRefresh(String key, final int expireSeconds, final Type type) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - T rs = convert.convertFrom(type, bucket.get()); - if (rs == null) return rs; - bucket.expire(expireSeconds, TimeUnit.SECONDS); - return rs; - } - - @Override - public CompletableFuture getStringAndRefreshAsync(String key, int expireSeconds) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.StringCodec.INSTANCE); - return completableFuture(bucket.getAsync().thenCompose(rs -> { - if (rs == null) return CompletableFuture.completedFuture(null); - return bucket.expireAsync(expireSeconds, TimeUnit.SECONDS).thenApply(v -> rs); - })); - } - - @Override - public String getStringAndRefresh(String key, final int expireSeconds) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.StringCodec.INSTANCE); - String rs = bucket.get(); - if (rs == null) return rs; - bucket.expire(expireSeconds, TimeUnit.SECONDS); - return rs; - } - - @Override - public CompletableFuture getLongAndRefreshAsync(String key, int expireSeconds, long defValue) { - final RAtomicLong bucket = redisson.getAtomicLong(key); - return completableFuture(bucket.getAsync().thenCompose(rs -> { - if (rs == null) return CompletableFuture.completedFuture(defValue); - return bucket.expireAsync(expireSeconds, TimeUnit.SECONDS).thenApply(v -> rs); - })); - } - - @Override - public long getLongAndRefresh(String key, final int expireSeconds, long defValue) { - final RAtomicLong bucket = redisson.getAtomicLong(key); - long rs = bucket.get(); - bucket.expire(expireSeconds, TimeUnit.SECONDS); - return rs; - } - - //--------------------- refresh ------------------------------ - @Override - public CompletableFuture refreshAsync(String key, int expireSeconds) { - final RBucket bucket = redisson.getBucket(key); - return completableFuture(bucket.expireAsync(expireSeconds, TimeUnit.SECONDS).thenApply(r -> null)); - } - - @Override - public void refresh(String key, final int expireSeconds) { - final RBucket bucket = redisson.getBucket(key); - bucket.expire(expireSeconds, TimeUnit.SECONDS); - } - - //--------------------- set ------------------------------ - @Override - @Deprecated - public CompletableFuture setAsync(String key, V value) { - return setAsync(key, objValueType, value); - } - - @Override - public CompletableFuture setAsync(String key, Convert convert0, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync((convert0 == null ? this.convert : convert0).convertToBytes(value))); - } - - @Override - public CompletableFuture setAsync(String key, final Type type, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync(this.convert.convertToBytes(type, value))); - } - - @Override - public CompletableFuture setAsync(String key, Convert convert0, final Type type, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync((convert0 == null ? this.convert : convert0).convertToBytes(type, value))); - } - - @Override - @Deprecated - public void set(final String key, V value) { - set(key, objValueType, value); - } - - @Override - public void set(final String key, final Convert convert0, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set((convert0 == null ? this.convert : convert0).convertToBytes(value)); - } - - @Override - public void set(final String key, final Type type, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set(this.convert.convertToBytes(type, value)); - } - - @Override - public void set(String key, final Convert convert0, final Type type, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set((convert0 == null ? this.convert : convert0).convertToBytes(type, value)); - } - - @Override - public CompletableFuture setStringAsync(String key, String value) { - return completableFuture(redisson.getBucket(key, org.redisson.client.codec.StringCodec.INSTANCE).setAsync(value)); - } - - @Override - public void setString(String key, String value) { - redisson.getBucket(key, org.redisson.client.codec.StringCodec.INSTANCE).set(value); - } - - @Override - public CompletableFuture setLongAsync(String key, long value) { - return completableFuture(redisson.getAtomicLong(key).setAsync(value)); - } - - @Override - public void setLong(String key, long value) { - redisson.getAtomicLong(key).set(value); - } - - //--------------------- set ------------------------------ - @Override - @Deprecated - public CompletableFuture setAsync(int expireSeconds, String key, V value) { - return setAsync(expireSeconds, key, objValueType, value); - } - - @Override - public CompletableFuture setAsync(int expireSeconds, String key, Convert convert0, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync((convert0 == null ? convert : convert0).convertToBytes(value)).thenCompose(v -> bucket.expireAsync(expireSeconds, TimeUnit.SECONDS)).thenApply(r -> null)); - } - - @Override - public CompletableFuture setAsync(int expireSeconds, String key, final Type type, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync(convert.convertToBytes(type, value)).thenCompose(v -> bucket.expireAsync(expireSeconds, TimeUnit.SECONDS)).thenApply(r -> null)); - } - - @Override - public CompletableFuture setAsync(int expireSeconds, String key, Convert convert0, final Type type, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync((convert0 == null ? convert : convert0).convertToBytes(type, value)).thenCompose(v -> bucket.expireAsync(expireSeconds, TimeUnit.SECONDS)).thenApply(r -> null)); - } - - @Override - @Deprecated - public void set(int expireSeconds, String key, V value) { - set(expireSeconds, key, objValueType, value); - } - - @Override - public void set(int expireSeconds, String key, Convert convert0, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set((convert0 == null ? convert : convert0).convertToBytes(value)); - bucket.expire(expireSeconds, TimeUnit.SECONDS); - } - - @Override - public void set(int expireSeconds, String key, final Type type, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set(convert.convertToBytes(type, value)); - bucket.expire(expireSeconds, TimeUnit.SECONDS); - } - - @Override - public void set(int expireSeconds, String key, Convert convert0, final Type type, T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set((convert0 == null ? convert : convert0).convertToBytes(type, value)); - bucket.expire(expireSeconds, TimeUnit.SECONDS); - } - - @Override - public CompletableFuture setStringAsync(int expireSeconds, String key, String value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.StringCodec.INSTANCE); - return completableFuture(bucket.setAsync(value).thenCompose(v -> bucket.expireAsync(expireSeconds, TimeUnit.SECONDS)).thenApply(r -> null)); - } - - @Override - public void setString(int expireSeconds, String key, String value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.StringCodec.INSTANCE); - bucket.set(value); - bucket.expire(expireSeconds, TimeUnit.SECONDS); - } - - @Override - public CompletableFuture setLongAsync(int expireSeconds, String key, long value) { - final RAtomicLong bucket = redisson.getAtomicLong(key); - return completableFuture(bucket.setAsync(value).thenCompose(v -> bucket.expireAsync(expireSeconds, TimeUnit.SECONDS)).thenApply(r -> null)); - } - - @Override - public void setLong(int expireSeconds, String key, long value) { - final RAtomicLong bucket = redisson.getAtomicLong(key); - bucket.set(value); - bucket.expire(expireSeconds, TimeUnit.SECONDS); - } - - //--------------------- setExpireSeconds ------------------------------ - @Override - public CompletableFuture setExpireSecondsAsync(String key, int expireSeconds) { - return completableFuture(redisson.getBucket(key).expireAsync(expireSeconds, TimeUnit.SECONDS).thenApply(r -> null)); - } - - @Override - public void setExpireSeconds(String key, int expireSeconds) { - redisson.getBucket(key).expire(expireSeconds, TimeUnit.SECONDS); - } - - //--------------------- remove ------------------------------ - @Override - public CompletableFuture removeAsync(String key) { - return completableFuture(redisson.getBucket(key).deleteAsync().thenApply(rs -> rs ? 1 : 0)); - } - - @Override - public int remove(String key) { - return redisson.getBucket(key).delete() ? 1 : 0; - } - - //--------------------- incr ------------------------------ - @Override - public long incr(final String key) { - return redisson.getAtomicLong(key).incrementAndGet(); - } - - @Override - public CompletableFuture incrAsync(final String key) { - return completableFuture(redisson.getAtomicLong(key).incrementAndGetAsync()); - } - - @Override - public long incr(final String key, long num) { - return redisson.getAtomicLong(key).addAndGet(num); - } - - @Override - public CompletableFuture incrAsync(final String key, long num) { - return completableFuture(redisson.getAtomicLong(key).addAndGetAsync(num)); - } - - //--------------------- decr ------------------------------ - @Override - public long decr(final String key) { - return redisson.getAtomicLong(key).decrementAndGet(); - } - - @Override - public CompletableFuture decrAsync(final String key) { - return completableFuture(redisson.getAtomicLong(key).decrementAndGetAsync()); - } - - @Override - public long decr(final String key, long num) { - return redisson.getAtomicLong(key).addAndGet(-num); - } - - @Override - public CompletableFuture decrAsync(final String key, long num) { - return completableFuture(redisson.getAtomicLong(key).addAndGetAsync(-num)); - } - - @Override - public int hremove(final String key, String... fields) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return (int) map.fastRemove(fields); - } - - @Override - public int hsize(final String key) { - return redisson.getMap(key, MapByteArrayCodec.instance).size(); - } - - @Override - public List hkeys(final String key) { - return (List) new ArrayList<>(redisson.getMap(key, MapStringCodec.instance).keySet()); - } - - @Override - public long hincr(final String key, String field) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return map.addAndGet(field, 1L); - } - - @Override - public long hincr(final String key, String field, long num) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return map.addAndGet(field, num); - } - - @Override - public long hdecr(final String key, String field) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return map.addAndGet(field, -1L); - } - - @Override - public long hdecr(final String key, String field, long num) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return map.addAndGet(field, num); - } - - @Override - public boolean hexists(final String key, String field) { - return redisson.getMap(key, MapByteArrayCodec.instance).containsKey(field); - } - - @Override - public void hset(final String key, final String field, final Convert convert0, final T value) { - if (value == null) return; - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - map.fastPut(field, (convert0 == null ? convert : convert0).convertToBytes(objValueType, value)); - } - - @Override - public void hset(final String key, final String field, final Type type, final T value) { - if (value == null) return; - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - map.fastPut(field, this.convert.convertToBytes(type, value)); - } - - @Override - public void hset(final String key, final String field, final Convert convert0, final Type type, final T value) { - if (value == null) return; - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - map.fastPut(field, (convert0 == null ? convert : convert0).convertToBytes(type, value)); - } - - @Override - public void hsetString(final String key, final String field, final String value) { - if (value == null) return; - RMap map = redisson.getMap(key, MapStringCodec.instance); - map.fastPut(field, value); - } - - @Override - public void hsetLong(final String key, final String field, final long value) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - map.fastPut(field, value); - } - - @Override - public void hmset(final String key, final Serializable... values) { - Map vals = new HashMap<>(); - for (int i = 0; i < values.length; i += 2) { - vals.put(String.valueOf(values[i]), this.convert.convertToBytes(values[i + 1])); - } - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - map.putAll(vals); - } - - @Override - public List hmget(final String key, final Type type, final String... fields) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - Map rs = map.getAll(Set.of(fields)); - List list = new ArrayList<>(fields.length); - for (String field : fields) { - byte[] bs = rs.get(field); - if (bs == null) { - list.add(null); - } else { - list.add(convert.convertFrom(type, bs)); - } - } - return list; - } - - @Override - public Map hmap(final String key, final Type type, int offset, int limit, String pattern) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - Iterator it = map.keySet(pattern, offset + limit).iterator(); - final Map rs = new HashMap<>(); - int index = -1; - while (it.hasNext()) { - if (++index < offset) continue; - if (index >= offset + limit) break; - String field = it.next(); - byte[] bs = map.get(field); - if (bs != null) rs.put(field, convert.convertFrom(type, bs)); - } - return rs; - } - - @Override - public Map hmap(final String key, final Type type, int offset, int limit) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - Iterator it = map.keySet(offset + limit).iterator(); - final Map rs = new HashMap<>(); - int index = -1; - while (it.hasNext()) { - if (++index < offset) continue; - if (index >= offset + limit) break; - String field = it.next(); - byte[] bs = map.get(field); - if (bs != null) rs.put(field, convert.convertFrom(type, bs)); - } - return rs; - } - - @Override - public T hget(final String key, final String field, final Type type) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - byte[] bs = map.get(field); - return bs == null ? null : convert.convertFrom(type, bs); - } - - @Override - public String hgetString(final String key, final String field) { - RMap map = redisson.getMap(key, MapStringCodec.instance); - return map.get(field); - } - - @Override - public long hgetLong(final String key, final String field, long defValue) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - Long rs = map.get(field); - return rs == null ? defValue : rs; - } - - @Override - public CompletableFuture hremoveAsync(final String key, String... fields) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return completableFuture(map.fastRemoveAsync(fields).thenApply(r -> r.intValue())); - } - - @Override - public CompletableFuture hsizeAsync(final String key) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return completableFuture(map.sizeAsync()); - } - - @Override - public CompletableFuture> hkeysAsync(final String key) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return completableFuture(map.readAllKeySetAsync().thenApply(set -> set == null ? null : new ArrayList(set))); - } - - @Override - public CompletableFuture hincrAsync(final String key, String field) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return completableFuture(map.addAndGetAsync(field, 1L)); - } - - @Override - public CompletableFuture hincrAsync(final String key, String field, long num) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return completableFuture(map.addAndGetAsync(field, num)); - } - - @Override - public CompletableFuture hdecrAsync(final String key, String field) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return completableFuture(map.addAndGetAsync(field, -1L)); - } - - @Override - public CompletableFuture hdecrAsync(final String key, String field, long num) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return completableFuture(map.addAndGetAsync(field, -num)); - } - - @Override - public CompletableFuture hexistsAsync(final String key, String field) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return completableFuture(map.containsKeyAsync(field)); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Convert convert0, final T value) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return completableFuture(map.fastPutAsync(field, (convert0 == null ? convert : convert0).convertToBytes(objValueType, value)).thenApply(r -> null)); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Type type, final T value) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return completableFuture(map.fastPutAsync(field, convert.convertToBytes(type, value)).thenApply(r -> null)); - } - - @Override - public CompletableFuture hsetAsync(final String key, final String field, final Convert convert0, final Type type, final T value) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return completableFuture(map.fastPutAsync(field, (convert0 == null ? convert : convert0).convertToBytes(type, value)).thenApply(r -> null)); - } - - @Override - public CompletableFuture hsetStringAsync(final String key, final String field, final String value) { - if (value == null) return CompletableFuture.completedFuture(null); - RMap map = redisson.getMap(key, MapStringCodec.instance); - return completableFuture(map.fastPutAsync(field, value).thenApply(r -> null)); - } - - @Override - public CompletableFuture hsetLongAsync(final String key, final String field, final long value) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return completableFuture(map.fastPutAsync(field, value).thenApply(r -> null)); - } - - @Override - public CompletableFuture hmsetAsync(final String key, final Serializable... values) { - Map vals = new HashMap<>(); - for (int i = 0; i < values.length; i += 2) { - vals.put(String.valueOf(values[i]), this.convert.convertToBytes(values[i + 1])); - } - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return completableFuture(map.putAllAsync(vals)); - } - - @Override - public CompletableFuture> hmgetAsync(final String key, final Type type, final String... fields) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return completableFuture(map.getAllAsync(Set.of(fields)).thenApply(rs -> { - List list = new ArrayList<>(fields.length); - for (String field : fields) { - byte[] bs = rs.get(field); - if (bs == null) { - list.add(null); - } else { - list.add(convert.convertFrom(type, bs)); - } - } - return list; - })); - } - - @Override - public CompletableFuture> hmapAsync(final String key, final Type type, int offset, int limit) { - return CompletableFuture.supplyAsync(() -> { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - - Iterator it = map.keySet(offset + limit).iterator(); - final Map rs = new HashMap<>(); - int index = -1; - while (it.hasNext()) { - if (++index < offset) continue; - if (index >= offset + limit) break; - String field = it.next(); - byte[] bs = map.get(field); - if (bs != null) rs.put(field, convert.convertFrom(type, bs)); - } - return rs; - }); - } - - @Override - public CompletableFuture> hmapAsync(final String key, final Type type, int offset, int limit, String pattern) { - return CompletableFuture.supplyAsync(() -> { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - - Iterator it = map.keySet(pattern, offset + limit).iterator(); - final Map rs = new HashMap<>(); - int index = -1; - while (it.hasNext()) { - if (++index < offset) continue; - if (index >= offset + limit) break; - String field = it.next(); - byte[] bs = map.get(field); - if (bs != null) rs.put(field, convert.convertFrom(type, bs)); - } - return rs; - }); - } - - @Override - public CompletableFuture hgetAsync(final String key, final String field, final Type type) { - RMap map = redisson.getMap(key, MapByteArrayCodec.instance); - return completableFuture(map.getAsync(field).thenApply(r -> r == null ? null : convert.convertFrom(type, r))); - } - - @Override - public CompletableFuture hgetStringAsync(final String key, final String field) { - RMap map = redisson.getMap(key, MapStringCodec.instance); - return completableFuture(map.getAsync(field)); - } - - @Override - public CompletableFuture hgetLongAsync(final String key, final String field, long defValue) { - RMap map = redisson.getMap(key, MapLongCodec.instance); - return completableFuture(map.getAsync(field).thenApply(r -> r == null ? defValue : r.longValue())); - } - - //--------------------- collection ------------------------------ - @Override - public CompletableFuture getCollectionSizeAsync(String key) { - return completableFuture(redisson.getScript().evalAsync(RScript.Mode.READ_ONLY, "return redis.call('TYPE', '" + key + "')", RScript.ReturnType.VALUE).thenCompose(type -> { - if (String.valueOf(type).contains("list")) { - return redisson.getList(key).sizeAsync(); - } else { - return redisson.getSet(key).sizeAsync(); - } - })); - } - - @Override - public int getCollectionSize(String key) { - String type = redisson.getScript().eval(RScript.Mode.READ_ONLY, "return redis.call('TYPE', '" + key + "')", RScript.ReturnType.VALUE); - if (String.valueOf(type).contains("list")) { - return redisson.getList(key).size(); - } else { - return redisson.getSet(key).size(); - } - } - - @Override - @Deprecated - public CompletableFuture> getCollectionAsync(String key) { - return getCollectionAsync(key, objValueType); - } - - @Override - public CompletableFuture> getCollectionAsync(String key, final Type componentType) { - return completableFuture(redisson.getScript().evalAsync(RScript.Mode.READ_ONLY, "return redis.call('TYPE', '" + key + "')", RScript.ReturnType.VALUE).thenCompose(type -> { - if (String.valueOf(type).contains("list")) { - return (CompletionStage) redisson.getList(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE).readAllAsync().thenApply(list -> { - if (list == null || list.isEmpty()) return list; - List rs = new ArrayList<>(); - for (Object item : list) { - byte[] bs = (byte[]) item; - if (bs == null) { - rs.add(null); - } else { - rs.add(convert.convertFrom(componentType, bs)); - } - } - return rs; - }); - } else { - return (CompletionStage) redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE).readAllAsync().thenApply(set -> { - if (set == null || set.isEmpty()) return set; - Set rs = new HashSet<>(); - for (Object item : set) { - byte[] bs = (byte[]) item; - if (bs == null) { - rs.add(null); - } else { - rs.add(convert.convertFrom(componentType, bs)); - } - } - return rs; - }); - } - })); -// return (CompletableFuture) send("TYPE", null, componentType, key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { -// if (t == null) return CompletableFuture.completedFuture(null); -// if (new String((byte[]) t).contains("list")) { //list -// return send("LRANGE", CacheEntryType.OBJECT, componentType, false, key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}); -// } else { -// return send("SMEMBERS", CacheEntryType.OBJECT, componentType, true, key, key.getBytes(StandardCharsets.UTF_8)); -// } -// }); - } - - @Override - public CompletableFuture> getLongMapAsync(String... keys) { - return completableFuture(redisson.getBuckets(org.redisson.client.codec.LongCodec.INSTANCE).getAsync(keys)); - } - - @Override - public CompletableFuture getLongArrayAsync(String... keys) { - return completableFuture(redisson.getBuckets(org.redisson.client.codec.LongCodec.INSTANCE).getAsync(keys).thenApply(map -> { - Long[] rs = new Long[keys.length]; - for (int i = 0; i < rs.length; i++) { - rs[i] = (Long) map.get(keys[i]); - } - return rs; - })); - } - - @Override - public CompletableFuture getStringArrayAsync(String... keys) { - return completableFuture(redisson.getBuckets(org.redisson.client.codec.StringCodec.INSTANCE).getAsync(keys).thenApply(map -> { - String[] rs = new String[keys.length]; - for (int i = 0; i < rs.length; i++) { - rs[i] = (String) map.get(keys[i]); - } - return rs; - })); - } - - @Override - public CompletableFuture> getStringMapAsync(String... keys) { - return completableFuture(redisson.getBuckets(org.redisson.client.codec.StringCodec.INSTANCE).getAsync(keys)); - } - - @Override - public CompletableFuture> getMapAsync(final Type componentType, String... keys) { - return completableFuture(redisson.getBuckets(org.redisson.client.codec.ByteArrayCodec.INSTANCE).getAsync(keys).thenApply(map -> { - Map rs = new HashMap(); - map.forEach((k, v) -> rs.put(k, convert.convertFrom(componentType, (byte[]) v))); - return rs; - })); - } - - @Override - public CompletableFuture>> getCollectionMapAsync(final boolean set, final Type componentType, final String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new HashMap<>(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - if (!set) { //list - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = completableFuture(redisson.getList(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE).readAllAsync().thenApply(list -> { - if (list == null || list.isEmpty()) return list; - List rs = new ArrayList<>(); - for (Object item : list) { - byte[] bs = (byte[]) item; - if (bs == null) { - rs.add(null); - } else { - rs.add(convert.convertFrom(componentType, bs)); - } - } - synchronized (map) { - map.put(key, rs); - } - return rs; - })); - } - } else { - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = completableFuture(redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE).readAllAsync().thenApply(list -> { - if (list == null || list.isEmpty()) return list; - List rs = new ArrayList<>(); - for (Object item : list) { - byte[] bs = (byte[]) item; - if (bs == null) { - rs.add(null); - } else { - rs.add(convert.convertFrom(componentType, bs)); - } - } - synchronized (map) { - map.put(key, rs); - } - return rs; - })); - } - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - @Deprecated - public Collection getCollection(String key) { - return getCollection(key, objValueType); - } - - @Override - public Collection getCollection(String key, final Type componentType) { - return (Collection) getCollectionAsync(key, componentType).join(); - } - - @Override - public Map getLongMap(final String... keys) { - return redisson.getBuckets(org.redisson.client.codec.LongCodec.INSTANCE).get(keys); - } - - @Override - public Long[] getLongArray(final String... keys) { - Map map = redisson.getBuckets(org.redisson.client.codec.LongCodec.INSTANCE).get(keys); - Long[] rs = new Long[keys.length]; - for (int i = 0; i < rs.length; i++) { - rs[i] = map.get(keys[i]); - } - return rs; - } - - @Override - public Map getStringMap(final String... keys) { - return redisson.getBuckets(org.redisson.client.codec.StringCodec.INSTANCE).get(keys); - } - - @Override - public String[] getStringArray(final String... keys) { - Map map = redisson.getBuckets(org.redisson.client.codec.StringCodec.INSTANCE).get(keys); - String[] rs = new String[keys.length]; - for (int i = 0; i < rs.length; i++) { - rs[i] = map.get(keys[i]); - } - return rs; - } - - @Override - public Map getMap(final Type componentType, final String... keys) { - Map map = redisson.getBuckets(org.redisson.client.codec.ByteArrayCodec.INSTANCE).get(keys); - Map rs = new HashMap(map.size()); - map.forEach((k, v) -> rs.put(k, convert.convertFrom(componentType, v))); - return rs; - } - - @Override - public Map> getCollectionMap(final boolean set, final Type componentType, String... keys) { - return (Map) getCollectionMapAsync(set, componentType, keys).join(); - } - - @Override - public CompletableFuture> getStringCollectionAsync(String key) { - return completableFuture(redisson.getScript().evalAsync(RScript.Mode.READ_ONLY, "return redis.call('TYPE', '" + key + "')", RScript.ReturnType.VALUE).thenCompose(type -> { - if (String.valueOf(type).contains("list")) { - return (CompletionStage) redisson.getList(key, org.redisson.client.codec.StringCodec.INSTANCE).readAllAsync(); - } else { - return (CompletionStage) redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE).readAllAsync().thenApply(s -> s == null ? null : new ArrayList(s)); - } - })); - } - - @Override - public CompletableFuture>> getStringCollectionMapAsync(final boolean set, String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new HashMap<>(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - if (!set) { //list - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = completableFuture(redisson.getList(key, org.redisson.client.codec.StringCodec.INSTANCE).readAllAsync().thenApply(r -> { - if (r != null) { - synchronized (map) { - map.put(key, (Collection) r); - } - } - return null; - })); - } - } else { - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = completableFuture(redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE).readAllAsync().thenApply(r -> { - if (r != null) { - synchronized (map) { - map.put(key, new ArrayList(r)); - } - } - return null; - })); - } - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - public Collection getStringCollection(String key) { - return getStringCollectionAsync(key).join(); - } - - @Override - public Map> getStringCollectionMap(final boolean set, String... keys) { - return getStringCollectionMapAsync(set, keys).join(); - } - - @Override - public CompletableFuture> getLongCollectionAsync(String key) { - return completableFuture(redisson.getScript().evalAsync(RScript.Mode.READ_ONLY, "return redis.call('TYPE', '" + key + "')", RScript.ReturnType.VALUE).thenCompose(type -> { - if (String.valueOf(type).contains("list")) { - return (CompletionStage) redisson.getList(key, org.redisson.client.codec.LongCodec.INSTANCE).readAllAsync(); - } else { - return (CompletionStage) redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE).readAllAsync().thenApply(s -> s == null ? null : new ArrayList(s)); - } - })); - } - - @Override - public CompletableFuture>> getLongCollectionMapAsync(final boolean set, String... keys) { - final CompletableFuture>> rsFuture = new CompletableFuture<>(); - final Map> map = new HashMap<>(); - final CompletableFuture[] futures = new CompletableFuture[keys.length]; - if (!set) { //list - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = completableFuture(redisson.getList(key, org.redisson.client.codec.LongCodec.INSTANCE).readAllAsync().thenApply(r -> { - if (r != null) { - synchronized (map) { - map.put(key, (Collection) r); - } - } - return null; - })); - } - } else { - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - futures[i] = completableFuture(redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE).readAllAsync().thenApply(r -> { - if (r != null) { - synchronized (map) { - map.put(key, new ArrayList(r)); - } - } - return null; - })); - } - } - CompletableFuture.allOf(futures).whenComplete((w, e) -> { - if (e != null) { - rsFuture.completeExceptionally(e); - } else { - rsFuture.complete(map); - } - }); - return rsFuture; - } - - @Override - public Collection getLongCollection(String key) { - return getLongCollectionAsync(key).join(); - } - - @Override - public Map> getLongCollectionMap(final boolean set, String... keys) { - return getLongCollectionMapAsync(set, keys).join(); - } - - //--------------------- getCollectionAndRefresh ------------------------------ - @Override - @Deprecated - public CompletableFuture> getCollectionAndRefreshAsync(String key, int expireSeconds) { - return getCollectionAndRefreshAsync(key, expireSeconds, objValueType); - } - - @Override - public CompletableFuture> getCollectionAndRefreshAsync(String key, int expireSeconds, final Type componentType) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getCollectionAsync(key, componentType)); - } - - @Override - @Deprecated - public Collection getCollectionAndRefresh(String key, final int expireSeconds) { - return getCollectionAndRefresh(key, expireSeconds, objValueType); - } - - @Override - public Collection getCollectionAndRefresh(String key, final int expireSeconds, final Type componentType) { - return (Collection) getCollectionAndRefreshAsync(key, expireSeconds, componentType).join(); - } - - @Override - public CompletableFuture> getStringCollectionAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getStringCollectionAsync(key)); - } - - @Override - public Collection getStringCollectionAndRefresh(String key, final int expireSeconds) { - return getStringCollectionAndRefreshAsync(key, expireSeconds).join(); - } - - @Override - public CompletableFuture> getLongCollectionAndRefreshAsync(String key, int expireSeconds) { - return (CompletableFuture) refreshAsync(key, expireSeconds).thenCompose(v -> getLongCollectionAsync(key)); - } - - @Override - public Collection getLongCollectionAndRefresh(String key, final int expireSeconds) { - return getLongCollectionAndRefreshAsync(key, expireSeconds).join(); - } - - //--------------------- existsItem ------------------------------ - @Override - @Deprecated - public boolean existsSetItem(String key, V value) { - return existsSetItem(key, objValueType, value); - } - - @Override - public boolean existsSetItem(String key, final Type componentType, T value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return bucket.contains(convert.convertToBytes(componentType, value)); - } - - @Override - @Deprecated - public CompletableFuture existsSetItemAsync(String key, V value) { - return existsSetItemAsync(key, objValueType, value); - } - - @Override - public CompletableFuture existsSetItemAsync(String key, final Type componentType, T value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.containsAsync(convert.convertToBytes(componentType, value))); - } - - @Override - public boolean existsStringSetItem(String key, String value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE); - return bucket.contains(value); - } - - @Override - public CompletableFuture existsStringSetItemAsync(String key, String value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE); - return completableFuture(bucket.containsAsync(value)); - } - - @Override - public boolean existsLongSetItem(String key, long value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE); - return bucket.contains(value); - } - - @Override - public CompletableFuture existsLongSetItemAsync(String key, long value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE); - return completableFuture(bucket.containsAsync(value)); - } - - //--------------------- appendListItem ------------------------------ - @Override - @Deprecated - public CompletableFuture appendListItemAsync(String key, V value) { - return appendListItemAsync(key, objValueType, value); - } - - @Override - public CompletableFuture appendListItemAsync(String key, final Type componentType, T value) { - final RList bucket = redisson.getList(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.addAsync(convert.convertToBytes(componentType, value)).thenApply(r -> null)); - } - - @Override - @Deprecated - public void appendListItem(String key, V value) { - appendListItem(key, objValueType, value); - } - - @Override - public void appendListItem(String key, final Type componentType, T value) { - final RList bucket = redisson.getList(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.add(convert.convertToBytes(componentType, value)); - } - - @Override - public CompletableFuture appendStringListItemAsync(String key, String value) { - final RList bucket = redisson.getList(key, org.redisson.client.codec.StringCodec.INSTANCE); - return completableFuture(bucket.addAsync(value).thenApply(r -> null)); - } - - @Override - public void appendStringListItem(String key, String value) { - final RList bucket = redisson.getList(key, org.redisson.client.codec.StringCodec.INSTANCE); - bucket.add(value); - } - - @Override - public CompletableFuture appendLongListItemAsync(String key, long value) { - final RList bucket = redisson.getList(key, org.redisson.client.codec.LongCodec.INSTANCE); - return completableFuture(bucket.addAsync(value).thenApply(r -> null)); - } - - @Override - public void appendLongListItem(String key, long value) { - final RList bucket = redisson.getList(key, org.redisson.client.codec.LongCodec.INSTANCE); - bucket.add(value); - } - - //--------------------- removeListItem ------------------------------ - @Override - @Deprecated - public CompletableFuture removeListItemAsync(String key, V value) { - return removeListItemAsync(key, objValueType, value); - } - - @Override - public CompletableFuture removeListItemAsync(String key, final Type componentType, T value) { - return completableFuture(redisson.getList(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE).removeAsync(convert.convertToBytes(componentType, value)).thenApply(r -> r ? 1 : 0)); - } - - @Override - @Deprecated - public int removeListItem(String key, V value) { - return removeListItem(key, objValueType, value); - } - - @Override - public int removeListItem(String key, final Type componentType, T value) { - final RList bucket = redisson.getList(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return bucket.remove(convert.convertToBytes(componentType, value)) ? 1 : 0; - } - - @Override - public CompletableFuture removeStringListItemAsync(String key, String value) { - return completableFuture(redisson.getList(key, org.redisson.client.codec.StringCodec.INSTANCE).removeAsync(value).thenApply(r -> r ? 1 : 0)); - } - - @Override - public int removeStringListItem(String key, String value) { - return redisson.getList(key, org.redisson.client.codec.StringCodec.INSTANCE).remove(value) ? 1 : 0; - } - - @Override - public CompletableFuture removeLongListItemAsync(String key, long value) { - return completableFuture(redisson.getList(key, org.redisson.client.codec.LongCodec.INSTANCE).removeAsync((Object) value).thenApply(r -> r ? 1 : 0)); - } - - @Override - public int removeLongListItem(String key, long value) { - return redisson.getList(key, org.redisson.client.codec.LongCodec.INSTANCE).remove((Object) value) ? 1 : 0; - } - - //--------------------- appendSetItem ------------------------------ - @Override - @Deprecated - public CompletableFuture appendSetItemAsync(String key, V value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.addAsync(convert.convertToBytes(objValueType, value)).thenApply(r -> null)); - } - - @Override - public CompletableFuture appendSetItemAsync(String key, Type componentType, T value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.addAsync(convert.convertToBytes(componentType, value)).thenApply(r -> null)); - } - - @Override - public CompletableFuture spopSetItemAsync(String key, Type componentType) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.removeRandomAsync().thenApply(bs -> bs == null ? null : convert.convertFrom(componentType, bs))); - } - - @Override - public CompletableFuture> spopSetItemAsync(String key, int count, Type componentType) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.removeRandomAsync(count).thenApply((Set bslist) -> { - if (bslist == null || bslist.isEmpty()) return new ArrayList<>(); - List rs = new ArrayList<>(); - for (byte[] bs : bslist) { - rs.add(convert.convertFrom(componentType, bs)); - } - return rs; - })); - } - - @Override - public CompletableFuture spopStringSetItemAsync(String key) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE); - return completableFuture(bucket.removeRandomAsync()); - } - - @Override - public CompletableFuture> spopStringSetItemAsync(String key, int count) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE); - return completableFuture(bucket.removeRandomAsync(count).thenApply(r -> r == null ? null : new ArrayList<>(r))); - } - - @Override - public CompletableFuture spopLongSetItemAsync(String key) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE); - return completableFuture(bucket.removeRandomAsync()); - } - - @Override - public CompletableFuture> spopLongSetItemAsync(String key, int count) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE); - return completableFuture(bucket.removeRandomAsync(count).thenApply(r -> r == null ? null : new ArrayList<>(r))); - } - - @Override - @Deprecated - public void appendSetItem(String key, V value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.add(convert.convertToBytes(objValueType, value)); - } - - @Override - public void appendSetItem(String key, final Type componentType, T value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.add(convert.convertToBytes(componentType, value)); - } - - @Override - public T spopSetItem(String key, final Type componentType) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - byte[] bs = bucket.removeRandom(); - return bs == null ? null : convert.convertFrom(componentType, bs); - } - - @Override - public List spopSetItem(String key, int count, final Type componentType) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - Set< byte[]> bslist = bucket.removeRandom(count); - List rs = new ArrayList<>(); - if (bslist == null) return rs; - for (byte[] bs : bslist) { - rs.add(convert.convertFrom(componentType, bs)); - } - return rs; - } - - @Override - public String spopStringSetItem(String key) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE); - return bucket.removeRandom(); - } - - @Override - public List spopStringSetItem(String key, int count) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE); - Set rs = bucket.removeRandom(count); - return rs == null ? null : new ArrayList<>(rs); - } - - @Override - public Long spopLongSetItem(String key) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE); - return bucket.removeRandom(); - } - - @Override - public List spopLongSetItem(String key, int count) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE); - Set rs = bucket.removeRandom(count); - return rs == null ? null : new ArrayList<>(rs); - } - - @Override - public CompletableFuture appendStringSetItemAsync(String key, String value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE); - return completableFuture(bucket.addAsync(value).thenApply(r -> null)); - } - - @Override - public void appendStringSetItem(String key, String value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE); - bucket.add(value); - } - - @Override - public CompletableFuture appendLongSetItemAsync(String key, long value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE); - return completableFuture(bucket.addAsync(value).thenApply(r -> null)); - } - - @Override - public void appendLongSetItem(String key, long value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE); - bucket.add(value); - } - - //--------------------- removeSetItem ------------------------------ - @Override - @Deprecated - public CompletableFuture removeSetItemAsync(String key, V value) { - return removeSetItemAsync(key, objValueType, value); - } - - @Override - public CompletableFuture removeSetItemAsync(String key, final Type componentType, T value) { - return completableFuture(redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE).removeAsync(convert.convertToBytes(componentType, value)).thenApply(r -> r ? 1 : 0)); - } - - @Override - @Deprecated - public int removeSetItem(String key, V value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return bucket.remove(convert.convertToBytes(objValueType, value)) ? 1 : 0; - } - - @Override - public int removeSetItem(String key, final Type componentType, T value) { - final RSet bucket = redisson.getSet(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return bucket.remove(convert.convertToBytes(componentType, value)) ? 1 : 0; - } - - @Override - public CompletableFuture removeStringSetItemAsync(String key, String value) { - return completableFuture(redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE).removeAsync(value).thenApply(r -> r ? 1 : 0)); - } - - @Override - public int removeStringSetItem(String key, String value) { - return redisson.getSet(key, org.redisson.client.codec.StringCodec.INSTANCE).remove(value) ? 1 : 0; - } - - @Override - public CompletableFuture removeLongSetItemAsync(String key, long value) { - return completableFuture(redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE).removeAsync(value).thenApply(r -> r ? 1 : 0)); - } - - @Override - public int removeLongSetItem(String key, long value) { - return redisson.getSet(key, org.redisson.client.codec.LongCodec.INSTANCE).remove(value) ? 1 : 0; - } - - //--------------------- queryKeys ------------------------------ - @Override - public List queryKeys() { - return redisson.getKeys().getKeysStream().collect(Collectors.toList()); - } - - @Override - public List queryKeysStartsWith(String startsWith) { - return redisson.getKeys().getKeysStreamByPattern(startsWith + "*").collect(Collectors.toList()); - } - - @Override - public List queryKeysEndsWith(String endsWith) { - return redisson.getKeys().getKeysStreamByPattern("*" + endsWith).collect(Collectors.toList()); - } - - @Override - public byte[] getBytes(final String key) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return bucket.get(); - } - - @Override - public byte[] getBytesAndRefresh(final String key, final int expireSeconds) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - byte[] bs = bucket.get(); - if (bs == null) return bs; - bucket.expire(expireSeconds, TimeUnit.SECONDS); - return bs; - } - - @Override - public void setBytes(final String key, final byte[] value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set(value); - } - - @Override - public void setBytes(final int expireSeconds, final String key, final byte[] value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set(value); - bucket.expire(expireSeconds, TimeUnit.SECONDS); - } - - @Override - public void setBytes(final String key, final Convert convert0, final Type type, final T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set((convert0 == null ? convert : convert0).convertToBytes(type, value)); - } - - @Override - public void setBytes(final int expireSeconds, final String key, final Convert convert0, final Type type, final T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - bucket.set((convert0 == null ? convert : convert0).convertToBytes(type, value)); - bucket.expire(expireSeconds, TimeUnit.SECONDS); - } - - @Override - public CompletableFuture getBytesAsync(final String key) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.getAsync()); - } - - @Override - public CompletableFuture getBytesAndRefreshAsync(final String key, final int expireSeconds) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.getAsync().thenCompose(bs -> bs == null ? CompletableFuture.completedFuture(null) : bucket.expireAsync(expireSeconds, TimeUnit.SECONDS).thenApply(v -> bs))); - } - - @Override - public CompletableFuture setBytesAsync(final String key, final byte[] value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync(value)); - } - - @Override - public CompletableFuture setBytesAsync(final int expireSeconds, final String key, final byte[] value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync(value).thenCompose(r -> bucket.expireAsync(expireSeconds, TimeUnit.SECONDS).thenApply(v -> null))); - } - - @Override - public CompletableFuture setBytesAsync(final String key, final Convert convert0, final Type type, final T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync((convert0 == null ? convert : convert0).convertToBytes(type, value)).thenApply(v -> null)); - } - - @Override - public CompletableFuture setBytesAsync(final int expireSeconds, final String key, final Convert convert0, final Type type, final T value) { - final RBucket bucket = redisson.getBucket(key, org.redisson.client.codec.ByteArrayCodec.INSTANCE); - return completableFuture(bucket.setAsync((convert0 == null ? convert : convert0).convertToBytes(type, value)).thenCompose(r -> bucket.expireAsync(expireSeconds, TimeUnit.SECONDS).thenApply(v -> null))); - } - - @Override - public CompletableFuture> queryKeysAsync() { - return CompletableFuture.supplyAsync(() -> queryKeys()); - } - - @Override - public CompletableFuture> queryKeysStartsWithAsync(String startsWith) { - if (startsWith == null) return CompletableFuture.supplyAsync(() -> queryKeys()); - return CompletableFuture.supplyAsync(() -> queryKeysStartsWith(startsWith)); - } - - @Override - public CompletableFuture> queryKeysEndsWithAsync(String endsWith) { - if (endsWith == null) return CompletableFuture.supplyAsync(() -> queryKeys()); - return CompletableFuture.supplyAsync(() -> queryKeysEndsWith(endsWith)); - } - - //--------------------- getKeySize ------------------------------ - @Override - public int getKeySize() { - return (int) redisson.getKeys().count(); - } - - @Override - public CompletableFuture getKeySizeAsync() { - return completableFuture(redisson.getKeys().countAsync().thenApply(r -> r.intValue())); - } - - //--------------------- queryList ------------------------------ - @Override - public List> queryList() { - return queryListAsync().join(); - } - - @Override - public CompletableFuture>> queryListAsync() { - return CompletableFuture.completedFuture(new ArrayList<>()); //不返回数据 - } - - protected static class MapByteArrayCodec extends org.redisson.client.codec.ByteArrayCodec { - - public static final MapByteArrayCodec instance = new MapByteArrayCodec(); - - @Override - public org.redisson.client.protocol.Decoder getMapKeyDecoder() { - return org.redisson.client.codec.StringCodec.INSTANCE.getValueDecoder(); - } - - @Override - public org.redisson.client.protocol.Encoder getMapKeyEncoder() { - return org.redisson.client.codec.StringCodec.INSTANCE.getValueEncoder(); - } - } - - protected static class MapStringCodec extends org.redisson.client.codec.StringCodec { - - public static final MapStringCodec instance = new MapStringCodec(); - - @Override - public org.redisson.client.protocol.Decoder getMapKeyDecoder() { - return org.redisson.client.codec.StringCodec.INSTANCE.getValueDecoder(); - } - - @Override - public org.redisson.client.protocol.Encoder getMapKeyEncoder() { - return org.redisson.client.codec.StringCodec.INSTANCE.getValueEncoder(); - } - } - - protected static class MapLongCodec extends org.redisson.client.codec.LongCodec { - - public static final MapLongCodec instance = new MapLongCodec(); - - @Override - public org.redisson.client.protocol.Decoder getMapKeyDecoder() { - return org.redisson.client.codec.StringCodec.INSTANCE.getValueDecoder(); - } - - @Override - public org.redisson.client.protocol.Encoder getMapKeyEncoder() { - return org.redisson.client.codec.StringCodec.INSTANCE.getValueEncoder(); - } - } -} -*/ diff --git a/src/com/zdemo/kafak/KafakConsumer.java b/src/com/zdemo/kafak/KafakConsumer.java deleted file mode 100644 index c4fc561..0000000 --- a/src/com/zdemo/kafak/KafakConsumer.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.zdemo.kafak; - -import com.zdemo.AbstractConsumer; -import com.zdemo.IConsumer; -import org.apache.kafka.clients.consumer.ConsumerRecords; -import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.common.errors.WakeupException; -import org.redkale.service.Service; -import org.redkale.util.AnyValue; -import org.redkale.util.AutoLoad; - -import javax.annotation.Resource; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.time.Duration; -import java.util.Properties; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * 消费 - */ -@AutoLoad(false) -public abstract class KafakConsumer extends AbstractConsumer implements IConsumer, Service { - - public Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - - @Resource(name = "APP_HOME") - protected File APP_HOME; - - private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); - - @Override - public final void init(AnyValue config) { - if (!preInit()) { - return; - } - try (FileInputStream fis = new FileInputStream(new File(APP_HOME, "conf/kafak.properties"));) { - Properties props = new Properties(); - props.load(fis); - - new Thread(() -> { - try { - props.put("group.id", getGroupid()); - KafkaConsumer consumer = new KafkaConsumer<>(props); - consumer.subscribe(getTopics()); - while (true) { - ConsumerRecords records = consumer.poll(Duration.ofMillis(1_000)); - records.forEach(record -> { - String topic = record.topic(); - long offset = record.offset(); - String value = record.value(); - try { - accept(topic, value); - } catch (Exception e) { - logger.log(Level.WARNING, String.format("topic[%s] event accept error, offset=%s,value:%s", topic, offset, value), e); - } - }); - - if (!queue.isEmpty()) { - Runnable runnable; - while ((runnable = queue.poll()) != null) { - runnable.run(); - } - - consumer.unsubscribe(); - consumer.subscribe(getTopics()); - } - } - } catch (WakeupException ex) { - System.out.println("WakeupException !!!!"); - } - - }, "thread-consumer-[" + getGroupid() + "]").start(); - } catch (IOException e) { - logger.log(Level.WARNING, "", e); - } - } - - @Override - public void unsubscribe(String topic) { - queue.add(() -> super.removeEventType(topic)); // 加入延时执行队列(下一次订阅变更检查周期执行) - } - - @Override - protected void subscribe(String topic) { - queue.add(() -> { - // just set flag, nothing to do - }); - } -} diff --git a/src/com/zdemo/kafak/KafakProducer.java b/src/com/zdemo/kafak/KafakProducer.java deleted file mode 100644 index 1c272a3..0000000 --- a/src/com/zdemo/kafak/KafakProducer.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.zdemo.kafak; - -import com.zdemo.IProducer; -import org.apache.kafka.clients.producer.KafkaProducer; -import org.apache.kafka.clients.producer.ProducerRecord; -import org.redkale.convert.json.JsonConvert; -import org.redkale.service.Service; -import org.redkale.util.AnyValue; -import org.redkale.util.AutoLoad; - -import javax.annotation.Resource; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; -import java.util.logging.Level; - -/** - * 生产 - * - * @param - */ -@AutoLoad(false) -public class KafakProducer implements IProducer, Service { - private KafkaProducer producer; - - @Resource(name = "APP_HOME") - protected File APP_HOME; - - @Override - public void init(AnyValue config) { - File file = new File(APP_HOME, "conf/kafak.properties"); - try (FileInputStream fis = new FileInputStream(file)) { - Properties props = new Properties(); - props.load(fis); - producer = new KafkaProducer(props); - } catch (IOException e) { - logger.log(Level.WARNING, "未初始化kafak 生产者,kafak发布消息不可用", e); - } - } - - @Override - public boolean publish(String topic, Object v) { - producer.send(new ProducerRecord(topic, toStr(v))); - return true; - } - - @Override - public void destroy(AnyValue config) { - producer.close(); - } - - private String toStr(V v) { - if (v instanceof String) { - return (String) v; - } - return JsonConvert.root().convertTo(v); - } -} diff --git a/src/com/zdemo/pulsar/AService.java b/src/com/zdemo/pulsar/AService.java deleted file mode 100644 index fe39874..0000000 --- a/src/com/zdemo/pulsar/AService.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.zdemo.pulsar; - -import com.zdemo.zhub.ZHubClient; -import org.redkale.net.http.RestMapping; -import org.redkale.net.http.RestService; -import org.redkale.service.Service; -import org.redkale.util.AnyValue; -import org.redkale.util.Utility; - -import javax.annotation.Resource; - -@RestService -public class AService implements Service { - - @Resource(name = "zhub") - private ZHubClient zhub; - - @Override - public void init(AnyValue config) { - zhub.timer("a", () -> { - System.out.println(Utility.now() + " timer RANK-DATA-RELOADALL 执行了"); - }); - } - - @RestMapping - public void x() { - - } -} diff --git a/src/com/zdemo/pulsar/PulsarConsumer.java b/src/com/zdemo/pulsar/PulsarConsumer.java deleted file mode 100644 index 3008e08..0000000 --- a/src/com/zdemo/pulsar/PulsarConsumer.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.zdemo.pulsar; - -import com.zdemo.AbstractConsumer; -import com.zdemo.EventType; -import com.zdemo.IConsumer; -import org.apache.pulsar.client.api.*; -import org.redkale.service.Service; -import org.redkale.util.AnyValue; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; - -public abstract class PulsarConsumer extends AbstractConsumer implements IConsumer, Service { - - @Resource(name = "property.pulsar.serviceurl") - private String serviceurl = "pulsar://127.0.0.1:6650"; - private PulsarClient client; - private Consumer consumer; - - public abstract String getGroupid(); - - private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); - - @Override - public void addEventType(EventType... eventTypes) { - super.addEventType(eventTypes); - - // 增加变更标记 - queue.add(() -> logger.info("PulsarConsumer add new topic!")); - } - - @Override - public void init(AnyValue config) { - if (!preInit()) { - return; - } - queue.add(() -> logger.info("PulsarConsumer starting ...")); - new Thread(() -> { - try { - client = PulsarClient.builder() - .serviceUrl(serviceurl) - .build(); - - while (true) { - // 动态新增订阅 - if (!queue.isEmpty()) { - Runnable runnable; - while ((runnable = queue.poll()) != null) { - runnable.run(); - } - - consumer.unsubscribe(); - consumer = client.newConsumer() - .topics(new ArrayList<>(getTopics())) - .subscriptionName(getGroupid()) - .subscriptionType(SubscriptionType.Shared) - .subscribe(); - } - - // Wait for a message - Message msg = consumer.receive(10, TimeUnit.SECONDS); - if (msg == null) { - continue; - } - - String topic = msg.getTopicName().replace("persistent://public/default/", ""); - long offset = 0; - String value = new String(msg.getData()); - try { - accept(topic, value); - - consumer.acknowledge(msg); // Acknowledge the message so that it can be deleted by the message broker - } catch (Exception e) { - logger.log(Level.WARNING, String.format("topic[%s] event accept error, offset=%s,value:%s", topic, offset, value), e); - consumer.negativeAcknowledge(msg); // Message failed to process, redeliver later - } - } - } catch (PulsarClientException e) { - e.printStackTrace(); - } - }).start(); - } - - @Override - public void unsubscribe(String topic) { - - } -} diff --git a/src/com/zdemo/pulsar/PulsarProducer.java b/src/com/zdemo/pulsar/PulsarProducer.java deleted file mode 100644 index 219efcc..0000000 --- a/src/com/zdemo/pulsar/PulsarProducer.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.zdemo.pulsar; - -import com.zdemo.Event; -import com.zdemo.IProducer; -import org.apache.pulsar.client.api.Producer; -import org.apache.pulsar.client.api.PulsarClient; -import org.apache.pulsar.client.api.PulsarClientException; -import org.redkale.convert.json.JsonConvert; -import org.redkale.service.Service; -import org.redkale.util.AnyValue; -import org.redkale.util.Comment; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; - -public class PulsarProducer implements IProducer, Service { - - @Resource(name = "property.pulsar.serviceurl") - private String serviceurl = "pulsar://127.0.0.1:6650"; - - @Comment("消息生产者") - private Map> producerMap = new HashMap(); - private PulsarClient client; - - @Override - public void init(AnyValue config) { - try { - client = PulsarClient.builder() - .serviceUrl(serviceurl) - .build(); - } catch (PulsarClientException e) { - e.printStackTrace(); - } - } - - public Producer getProducer(String topic) { - Producer producer = producerMap.get(topic); - if (producer != null) { - return producer; - } - - synchronized (this) { - if ((producer = producerMap.get(topic)) == null) { - try { - producer = client.newProducer() - .topic(topic) - .batchingMaxPublishDelay(10, TimeUnit.MILLISECONDS) - .sendTimeout(10, TimeUnit.SECONDS) - .blockIfQueueFull(true) - .create(); - producerMap.put(topic, producer); - - return producer; - } catch (PulsarClientException e) { - e.printStackTrace(); - } - } - } - return producer; - } - - @Override - public void send(T t) { - try { - Producer producer = getProducer(t.topic); - - String v = JsonConvert.root().convertTo(t.value); - if (v.startsWith("\"") && v.endsWith("\"")) { - v = v.substring(1, v.length() - 1); - } - producer.newMessage() - .key("") - .value(v.getBytes()) - .send(); - } catch (Exception e) { - logger.log(Level.WARNING, "", e); - } - } -} diff --git a/src/com/zdemo/redis/RedisConsumer.java b/src/com/zdemo/redis/RedisConsumer.java deleted file mode 100644 index 5c59665..0000000 --- a/src/com/zdemo/redis/RedisConsumer.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.zdemo.redis; - -import com.zdemo.AbstractConsumer; -import com.zdemo.IConsumer; -import org.redkale.service.Service; -import org.redkale.util.AnyValue; -import org.redkale.util.AutoLoad; - -import javax.annotation.Resource; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.logging.Level; -import java.util.logging.Logger; - -@AutoLoad(false) -public class RedisConsumer extends AbstractConsumer implements IConsumer, Service { - - public Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - - @Resource(name = "property.redis.host") - private String host = "127.0.0.1"; - @Resource(name = "property.redis.password") - private String password = ""; - @Resource(name = "property.redis.port") - private int port = 6379; - - private Socket client; - private OutputStreamWriter writer; - private BufferedReader reader; - - @Override - public void init(AnyValue config) { - try { - client = new Socket(); - client.connect(new InetSocketAddress(host, port)); - client.setKeepAlive(true); - - writer = new OutputStreamWriter(client.getOutputStream()); - writer.write("AUTH " + password + "\r\n"); - writer.flush(); - - StringBuffer buf = new StringBuffer("SUBSCRIBE"); - for (String topic : getTopics()) { - buf.append(" ").append(topic); - } - buf.append("\r\n"); - writer.write(buf.toString()); - writer.flush(); - - reader = new BufferedReader(new InputStreamReader(client.getInputStream())); - } catch (IOException e) { - logger.log(Level.WARNING, "Redis Consumer 初始化失败!", e); - } - - new Thread(() -> { - try { - while (true) { - String readLine = reader.readLine(); - String type = ""; - if ("*3".equals(readLine)) { - readLine = reader.readLine(); // $7 len() - type = reader.readLine(); // message - if (!"message".equals(type)) { - continue; - } - reader.readLine(); //$n len(key) - String topic = reader.readLine(); // topic - - reader.readLine(); //$n len(value) - String value = reader.readLine(); // value - try { - accept(topic, value); - } catch (Exception e) { - logger.log(Level.WARNING, "topic[" + topic + "] event accept error :" + value, e); - } - } - } - } catch (IOException e) { - logger.log(Level.WARNING, "", e); - } - }).start(); - } - - @Override - protected String getGroupid() { - return null; - } - - @Override - public void unsubscribe(String topic) { - try { - writer.write("UNSUBSCRIBE " + topic + "\r\n"); - writer.flush(); - } catch (IOException e) { - logger.log(Level.WARNING, "", e); - } - super.removeEventType(topic); - } - - @Override - protected void subscribe(String topic) { - //新增订阅 - try { - writer.write("SUBSCRIBE " + topic + "\r\n"); - writer.flush(); - } catch (IOException e) { - logger.log(Level.WARNING, "", e); - } - } -} diff --git a/src/com/zdemo/redis/RedisProducer.java b/src/com/zdemo/redis/RedisProducer.java deleted file mode 100644 index 91bc7f2..0000000 --- a/src/com/zdemo/redis/RedisProducer.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.zdemo.redis; - -import com.zdemo.IProducer; -import org.redkale.convert.json.JsonConvert; -import org.redkale.service.Service; -import org.redkale.util.AnyValue; -import org.redkale.util.AutoLoad; - -import javax.annotation.Resource; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.logging.Level; - -@AutoLoad(false) -public class RedisProducer implements IProducer, Service { - - @Resource(name = "property.redis.host") - private String host = "127.0.0.1"; - @Resource(name = "property.redis.password") - private String password = ""; - @Resource(name = "property.redis.port") - private int port = 6379; - - private OutputStreamWriter osw; - - @Override - public void init(AnyValue config) { - try { - Socket client = new Socket(); - client.connect(new InetSocketAddress(host, port)); - client.setKeepAlive(true); - - osw = new OutputStreamWriter(client.getOutputStream()); - osw.write("AUTH " + password + "\r\n"); - osw.flush(); - } catch (IOException e) { - logger.log(Level.WARNING, "", e); - } - } - - @Override - public boolean publish(String topic, Object v) { - try { - osw.write("PUBLISH " + topic + " '" + toStr(v) + "' \r\n"); - osw.flush(); - return true; - } catch (IOException e) { - logger.log(Level.WARNING, "", e); - } - return false; - } - - private String toStr(Object v) { - if (v instanceof String) { - return (String) v; - } - return JsonConvert.root().convertTo(v); - } -} diff --git a/src/main/java/META-INF/services/org.redkale.cluster.ClusterAgentProvider b/src/main/java/META-INF/services/org.redkale.cluster.ClusterAgentProvider new file mode 100644 index 0000000..ecd69d4 --- /dev/null +++ b/src/main/java/META-INF/services/org.redkale.cluster.ClusterAgentProvider @@ -0,0 +1 @@ +net.tccn.ZhubProvider \ No newline at end of file diff --git a/src/main/java/META-INF/services/org.redkale.source.CacheSourceProvider b/src/main/java/META-INF/services/org.redkale.source.CacheSourceProvider new file mode 100644 index 0000000..41677c1 --- /dev/null +++ b/src/main/java/META-INF/services/org.redkale.source.CacheSourceProvider @@ -0,0 +1 @@ +org.redkalex.cache.redis.RedisCacheSourceProvider \ No newline at end of file diff --git a/src/com/zdemo/AbstractConsumer.java b/src/main/java/net/tccn/AbstractConsumer.java similarity index 85% rename from src/com/zdemo/AbstractConsumer.java rename to src/main/java/net/tccn/AbstractConsumer.java index db3e02b..f126411 100644 --- a/src/com/zdemo/AbstractConsumer.java +++ b/src/main/java/net/tccn/AbstractConsumer.java @@ -1,9 +1,9 @@ -package com.zdemo; +package net.tccn; import org.redkale.convert.json.JsonConvert; +import org.redkale.util.Resourcable; import org.redkale.util.TypeToken; -import javax.annotation.Resource; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -13,21 +13,16 @@ import java.util.function.Consumer; * @author Liang * @data 2020-09-05 23:18 */ -public abstract class AbstractConsumer implements IConsumer { +public abstract class AbstractConsumer extends ZhubAgentProvider implements IConsumer, Resourcable { protected JsonConvert convert = JsonConvert.root(); - @Resource(name = "APP_NAME") - protected String APP_NAME = ""; + protected static String APP_NAME = ""; private Map eventMap = new ConcurrentHashMap<>(); protected abstract String getGroupid(); - protected boolean preInit() { - return true; - } - protected final Set getTopics() { if (!eventMap.isEmpty()) { return eventMap.keySet(); @@ -76,4 +71,10 @@ public abstract class AbstractConsumer implements IConsumer { } } + // -------------- + + @Override + public String resourceName() { + return super.getName(); + } } diff --git a/src/com/zdemo/Event.java b/src/main/java/net/tccn/Event.java similarity index 95% rename from src/com/zdemo/Event.java rename to src/main/java/net/tccn/Event.java index ce5318b..cc957c6 100644 --- a/src/com/zdemo/Event.java +++ b/src/main/java/net/tccn/Event.java @@ -1,4 +1,4 @@ -package com.zdemo; +package net.tccn; /** * 发布订阅 事件 diff --git a/src/com/zdemo/EventType.java b/src/main/java/net/tccn/EventType.java similarity index 97% rename from src/com/zdemo/EventType.java rename to src/main/java/net/tccn/EventType.java index e82e9fa..4c24d9a 100644 --- a/src/com/zdemo/EventType.java +++ b/src/main/java/net/tccn/EventType.java @@ -1,4 +1,4 @@ -package com.zdemo; +package net.tccn; import org.redkale.util.TypeToken; diff --git a/src/com/zdemo/IConsumer.java b/src/main/java/net/tccn/IConsumer.java similarity index 96% rename from src/com/zdemo/IConsumer.java rename to src/main/java/net/tccn/IConsumer.java index 60126ca..963803e 100644 --- a/src/com/zdemo/IConsumer.java +++ b/src/main/java/net/tccn/IConsumer.java @@ -1,4 +1,4 @@ -package com.zdemo; +package net.tccn; import org.redkale.util.TypeToken; diff --git a/src/com/zdemo/IProducer.java b/src/main/java/net/tccn/IProducer.java similarity index 90% rename from src/com/zdemo/IProducer.java rename to src/main/java/net/tccn/IProducer.java index b5c8329..1ff3bd8 100644 --- a/src/com/zdemo/IProducer.java +++ b/src/main/java/net/tccn/IProducer.java @@ -1,4 +1,4 @@ -package com.zdemo; +package net.tccn; import java.util.logging.Logger; diff --git a/src/com/zdemo/IType.java b/src/main/java/net/tccn/IType.java similarity index 97% rename from src/com/zdemo/IType.java rename to src/main/java/net/tccn/IType.java index 2e89fbd..7943153 100644 --- a/src/com/zdemo/IType.java +++ b/src/main/java/net/tccn/IType.java @@ -1,4 +1,4 @@ -package com.zdemo; +package net.tccn; import org.redkale.util.TypeToken; diff --git a/src/com/zdemo/cachex/RedisTest.java b/src/main/java/net/tccn/RedisTest.java similarity index 64% rename from src/com/zdemo/cachex/RedisTest.java rename to src/main/java/net/tccn/RedisTest.java index 04cf9ed..f7e75fb 100644 --- a/src/com/zdemo/cachex/RedisTest.java +++ b/src/main/java/net/tccn/RedisTest.java @@ -1,23 +1,184 @@ -package com.zdemo.cachex; +package net.tccn; -import org.redkale.convert.json.JsonFactory; +import org.redkale.net.AsyncIOGroup; import org.redkale.util.AnyValue; +import org.redkale.util.ResourceFactory; +import org.redkalex.cache.redis.MyRedisCacheSource; + +import static org.redkale.boot.Application.RESNAME_APP_CLIENT_ASYNCGROUP; +import static org.redkale.source.AbstractCacheSource.*; public class RedisTest { - static MyRedisCacheSource source = new MyRedisCacheSource(); + static MyRedisCacheSource source = new MyRedisCacheSource(); - static { - AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue(); + static { // redis://:*Zhong9307!@47.111.150.118:6064?db=2 + AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue().addValue(CACHE_SOURCE_MAXCONNS, "1"); + conf.addValue(CACHE_SOURCE_NODE, new AnyValue.DefaultAnyValue().addValue(CACHE_SOURCE_URL, "redis://:123456@127.0.0.1:6379?db=0")); + final ResourceFactory factory = ResourceFactory.create(); + final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16); + asyncGroup.start(); + factory.register(RESNAME_APP_CLIENT_ASYNCGROUP, asyncGroup); + factory.inject(source); + //source.defaultConvert = JsonFactory.root().getConvert(); + source.init(conf); + + System.out.println(source.get("a")); + + //--------------------- bit ------------------------------ + /*boolean ax = source.getBit("ax", 6); + System.out.println("ax:"+ ax); + source.setBit("ax", 6, true); + + ax = source.getBit("ax", 6); + System.out.println("ax:"+ ax); + + source.setBit("ax", 6, false); + ax = source.getBit("ax", 6); + System.out.println("ax:"+ ax);*/ + //--------------------- bit ------------------------------ + + //--------------------- bit ------------------------------ + + /* + source.lock("lockx", 5000); + */ + + + source.keysStartsWith("more-hot").forEach(x -> { + System.out.println(x); + source.del(x); + + int i = (short) 3; + }); + + source.keysStartsWith("districtbeans").forEach(x -> { + System.out.println(x); + source.del(x); + }); + source.keysStartsWith("oss-blind-users").forEach(x -> { + System.out.println(x); + source.del(x); + }); + source.keysStartsWith("venue:drama-product-schedule-fee:rt-lbeuai84:20221217").forEach(x -> { + System.out.println(x); + source.del(x); + }); + source.keysStartsWith("venue:site-hour-fee:54f6e9b74cd7416db8d605366c1f49c2:20220729").forEach(x -> { + System.out.println(x); + source.del(x); + }); + source.keysStartsWith("rainbow").forEach(x -> { + System.out.println(x); + source.del(x); + }); + source.keysStartsWith("run").forEach(x -> { + System.out.println(x); + source.del(x); + }); + source.keysStartsWith("today").forEach(x -> { + System.out.println(x); + source.del(x); + }); + source.keysStartsWith("user").forEach(x -> { + System.out.println(x); + source.del(x); + }); + source.keysStartsWith("im:").forEach(x -> { + System.out.println(x); + source.del(x); + }); + source.keysStartsWith("ios-").forEach(x -> { + System.out.println(x); + source.del(x); + }); + + + //--------------------- set ------------------------------ + /*source.del("setx"); + *//* + int[] ints = {1, 2, 3}; + source.sadd("setx", ints); + *//* + + //source.sadd("setx", list.toArray(Integer[]::new)); + List list = List.of(2, 3, 5); + // source.sadd("setx", list.toArray(Integer[]::new)); + source.sadd("setx", list.toArray(Integer[]::new)); + source.sadd("setx", 12, 2312, 213); + source.sadd("setx", List.of(1011, 10222)); + + source.keys("setx*").forEach(x -> { + System.out.println(x); + }); + + source.srem("setx", 213, 2312); + + + Collection setx1 = source.getCollection("setx", String.class); + + System.out.println(setx1); + + + //source.getexLong() + + source.setHms("hmx", Map.of("a", "5", "b", "51", "c", "ads")); + + List hmget = source.hmget("hmx", int.class, "a"); + + System.out.println(hmget); + + Integer hm = source.getHm("hmx", int.class, "ads"); + System.out.println(hm); + + Map hms = source.getHms("hmx", "a", "b"); + System.out.println("hmx:" + hms); + + *//*System.out.println("======================================================"); + System.out.println(source.incrHm("hmx", "a", -6.0)); + hms = source.getHms("hmx", "a", "b"); + System.out.println("hmx:a+1后的结果 " + hms);*//* + System.out.println("======================================================"); + source.setHm("hmx", "c", 12); + hms = source.getHms("hmx", "a", "b", "c", "d", "a"); + System.out.println("hmx:设置 c=12 后的结果 " + hms); + System.out.println("======================================================"); + Double c = source.getHm("hmx", double.class, "c"); + System.out.println("hmx 中 c 值:" + c);*/ + + /*Map hmx = source.getHmall("hmx"); + System.out.println("Hmall:" + hmx);*/ + + + + + /*AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue(); conf.addValue("node", new AnyValue.DefaultAnyValue().addValue("addr", "47.111.150.118").addValue("port", "6064").addValue("password", "*Zhong9307!").addValue("db", 2)); source.defaultConvert = JsonFactory.root().getConvert(); source.initValueType(String.class); //value用String类型 - source.init(conf); + source.init(conf);*/ } public static void main(String[] args) { + + //source.setLong("a", 125); + + /*long a = source.getLong("a", 0); + System.out.println(a); + + List keys = source.keys("farm*"); + keys.forEach(x -> System.out.println(x)); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + }*/ + + + // =========================================== //System.out.println(source.remove("a", "b")); // bit @@ -118,11 +279,6 @@ public class RedisTest { System.out.println(k + " : " + v); });*/ - source.queryKeysStartsWith("ywb:").forEach(x -> { - System.out.println(x); - source.remove(x); - }); - /*MyRedisCacheSource source2 = new MyRedisCacheSource(); source2.defaultConvert = JsonFactory.root().getConvert(); diff --git a/src/main/java/net/tccn/ZhubAgentProvider.java b/src/main/java/net/tccn/ZhubAgentProvider.java new file mode 100644 index 0000000..7f9f3c1 --- /dev/null +++ b/src/main/java/net/tccn/ZhubAgentProvider.java @@ -0,0 +1,69 @@ +package net.tccn; + +import org.redkale.boot.Application; +import org.redkale.boot.NodeServer; +import org.redkale.cluster.CacheClusterAgent; +import org.redkale.cluster.ClusterAgent; +import org.redkale.service.Service; +import org.redkale.util.ResourceEvent; + +import java.net.InetSocketAddress; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +public abstract class ZhubAgentProvider extends ClusterAgent { + + @Override + public void onResourceChange(ResourceEvent[] events) { + + } + + @Override + public void register(Application application) { + + } + + @Override + public void deregister(Application application) { + + } + + @Override + public CompletableFuture>> queryMqtpAddress(String protocol, String module, String resname) { + return null; + } + + @Override + public CompletableFuture> queryHttpAddress(String protocol, String module, String resname) { + return null; + } + + @Override + public CompletableFuture> querySncpAddress(String protocol, String restype, String resname) { + return null; + } + + @Override + protected CompletableFuture> queryAddress(ClusterEntry entry) { + return null; + } + + @Override + protected ClusterEntry register(NodeServer ns, String protocol, Service service) { + deregister(ns, protocol, service); + ClusterEntry clusterEntry = new ClusterEntry(ns, protocol, service); + CacheClusterAgent.AddressEntry entry = new CacheClusterAgent.AddressEntry(); + entry.addr = clusterEntry.address; + entry.resname = clusterEntry.resourceName; + entry.nodeid = this.nodeid; + entry.time = System.currentTimeMillis(); + //source.hset(clusterEntry.serviceName, clusterEntry.serviceid, CacheClusterAgent.AddressEntry.class, entry); + return clusterEntry; + } + + @Override + protected void deregister(NodeServer ns, String protocol, Service service) { + + } +} diff --git a/src/main/java/net/tccn/ZhubProvider.java b/src/main/java/net/tccn/ZhubProvider.java new file mode 100644 index 0000000..737f557 --- /dev/null +++ b/src/main/java/net/tccn/ZhubProvider.java @@ -0,0 +1,21 @@ +package net.tccn; + +import net.tccn.zhub.ZHubClient; +import org.redkale.annotation.Priority; +import org.redkale.cluster.ClusterAgent; +import org.redkale.cluster.ClusterAgentProvider; +import org.redkale.util.AnyValue; + +@Priority(1) +public class ZhubProvider implements ClusterAgentProvider { + + @Override + public boolean acceptsConf(AnyValue config) { + return new ZHubClient().acceptsConf(config); + } + + @Override + public ClusterAgent createInstance() { + return new ZHubClient(); + } +} diff --git a/src/net/tccn/timer/TimerExecutor.java b/src/main/java/net/tccn/timer/TimerExecutor.java similarity index 100% rename from src/net/tccn/timer/TimerExecutor.java rename to src/main/java/net/tccn/timer/TimerExecutor.java diff --git a/src/net/tccn/timer/TimerTask.java b/src/main/java/net/tccn/timer/TimerTask.java similarity index 100% rename from src/net/tccn/timer/TimerTask.java rename to src/main/java/net/tccn/timer/TimerTask.java diff --git a/src/net/tccn/timer/Timers.java b/src/main/java/net/tccn/timer/Timers.java similarity index 100% rename from src/net/tccn/timer/Timers.java rename to src/main/java/net/tccn/timer/Timers.java diff --git a/src/net/tccn/timer/queue/TimerQueue.java b/src/main/java/net/tccn/timer/queue/TimerQueue.java similarity index 100% rename from src/net/tccn/timer/queue/TimerQueue.java rename to src/main/java/net/tccn/timer/queue/TimerQueue.java diff --git a/src/net/tccn/timer/scheduled/Scheduled.java b/src/main/java/net/tccn/timer/scheduled/Scheduled.java similarity index 100% rename from src/net/tccn/timer/scheduled/Scheduled.java rename to src/main/java/net/tccn/timer/scheduled/Scheduled.java diff --git a/src/net/tccn/timer/scheduled/ScheduledCycle.java b/src/main/java/net/tccn/timer/scheduled/ScheduledCycle.java similarity index 100% rename from src/net/tccn/timer/scheduled/ScheduledCycle.java rename to src/main/java/net/tccn/timer/scheduled/ScheduledCycle.java diff --git a/src/net/tccn/timer/scheduled/ScheduledExpres.java b/src/main/java/net/tccn/timer/scheduled/ScheduledExpres.java similarity index 100% rename from src/net/tccn/timer/scheduled/ScheduledExpres.java rename to src/main/java/net/tccn/timer/scheduled/ScheduledExpres.java diff --git a/src/net/tccn/timer/task/Job.java b/src/main/java/net/tccn/timer/task/Job.java similarity index 100% rename from src/net/tccn/timer/task/Job.java rename to src/main/java/net/tccn/timer/task/Job.java diff --git a/src/net/tccn/timer/task/Task.java b/src/main/java/net/tccn/timer/task/Task.java similarity index 100% rename from src/net/tccn/timer/task/Task.java rename to src/main/java/net/tccn/timer/task/Task.java diff --git a/src/com/zdemo/zhub/Lock.java b/src/main/java/net/tccn/zhub/Lock.java similarity index 95% rename from src/com/zdemo/zhub/Lock.java rename to src/main/java/net/tccn/zhub/Lock.java index 141cc3c..516a670 100644 --- a/src/com/zdemo/zhub/Lock.java +++ b/src/main/java/net/tccn/zhub/Lock.java @@ -1,4 +1,4 @@ -package com.zdemo.zhub; +package net.tccn.zhub; // ================================================== lock ================================================== public class Lock { diff --git a/src/com/zdemo/zhub/Rpc.java b/src/main/java/net/tccn/zhub/Rpc.java similarity index 75% rename from src/com/zdemo/zhub/Rpc.java rename to src/main/java/net/tccn/zhub/Rpc.java index d251223..5d1aaeb 100644 --- a/src/com/zdemo/zhub/Rpc.java +++ b/src/main/java/net/tccn/zhub/Rpc.java @@ -1,4 +1,4 @@ -package com.zdemo.zhub; +package net.tccn.zhub; import org.redkale.convert.ConvertColumn; import org.redkale.convert.json.JsonConvert; @@ -58,15 +58,7 @@ public class Rpc { return ruk.split("::")[0]; } - @Deprecated(since = "2023.04.15") - public RpcResult buildResp() { - RpcResult response = new RpcResult<>(); - response.setRuk(ruk); - return response; - } - - @Deprecated(since = "2023.04.15") - public RpcResult buildResp(int retcode, String retinfo) { + public RpcResult render(int retcode, String retinfo) { RpcResult response = new RpcResult<>(); response.setRuk(ruk); response.setRetcode(retcode); @@ -74,23 +66,6 @@ public class Rpc { return response; } - @Deprecated(since = "2023.04.15") - public RpcResult buildError(String retinfo) { - RpcResult response = new RpcResult<>(); - response.setRuk(ruk); - response.setRetcode(100); - response.setRetinfo(retinfo); - return response; - } - - @Deprecated(since = "2023.04.15") - public RpcResult buildResp(R result) { - RpcResult response = new RpcResult<>(); - response.setRuk(ruk); - response.setResult(result); - return response; - } - public RpcResult render() { RpcResult response = new RpcResult<>(); response.setRuk(ruk); diff --git a/src/com/zdemo/zhub/RpcResult.java b/src/main/java/net/tccn/zhub/RpcResult.java similarity index 96% rename from src/com/zdemo/zhub/RpcResult.java rename to src/main/java/net/tccn/zhub/RpcResult.java index 069b185..6f5bf87 100644 --- a/src/com/zdemo/zhub/RpcResult.java +++ b/src/main/java/net/tccn/zhub/RpcResult.java @@ -1,4 +1,4 @@ -package com.zdemo.zhub; +package net.tccn.zhub; public class RpcResult { private String ruk; diff --git a/src/com/zdemo/zhub/ZHubClient.java b/src/main/java/net/tccn/zhub/ZHubClient.java similarity index 60% rename from src/com/zdemo/zhub/ZHubClient.java rename to src/main/java/net/tccn/zhub/ZHubClient.java index f48c867..702e209 100644 --- a/src/com/zdemo/zhub/ZHubClient.java +++ b/src/main/java/net/tccn/zhub/ZHubClient.java @@ -1,9 +1,15 @@ -package com.zdemo.zhub; +package net.tccn.zhub; -import com.zdemo.*; +import net.tccn.*; import net.tccn.timer.Timers; +import org.redkale.annotation.AutoLoad; +import org.redkale.annotation.ResourceType; +import org.redkale.service.Local; import org.redkale.service.Service; -import org.redkale.util.*; +import org.redkale.util.AnyValue; +import org.redkale.util.Comment; +import org.redkale.util.TypeToken; +import org.redkale.util.Utility; import java.io.BufferedReader; import java.io.IOException; @@ -22,7 +28,9 @@ import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; -@AutoLoad(value = false) +@Local +@AutoLoad(false) +@ResourceType(ZHubClient.class) public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer, Service { public Logger logger = Logger.getLogger(ZHubClient.class.getSimpleName()); @@ -30,6 +38,7 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer private String auth = ""; private String groupid = ""; + //private ReentrantLock lock = new ReentrantLock(); private Socket client; private OutputStream writer; private BufferedReader reader; @@ -40,6 +49,12 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer private final LinkedBlockingQueue> rpcCallQueue = new LinkedBlockingQueue<>(); // RPC CALL MSG private final LinkedBlockingQueue sendMsgQueue = new LinkedBlockingQueue<>(); // SEND MSG + /*private BiConsumer threadBuilder = (r, n) -> { + for (int i = 0; i < n; i++) { + new Thread(() -> r.run()).start(); + } + };*/ + private static Map mainHub = new HashMap<>(); // 127.0.0.1:1216 - ZHubClient public ZHubClient() { @@ -52,15 +67,28 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer this.groupid = attr.get("groupid"); this.auth = attr.get("auth"); - this.init(null); + this.initClient(null); } @Override public void init(AnyValue config) { - if (!preInit()) { + APP_NAME = application.getName(); + /*if (!preInit()) { return; - } + }*/ + if (config == null) { + initClient(null); + } else { + Map nodes = getNodes(config); + for (String rsName : nodes.keySet()) { + ZHubClient client = new ZHubClient().initClient(nodes.get(rsName)); + application.getResourceFactory().register(rsName, client); + } + } + } + + private ZHubClient initClient(AnyValue config) { // 自动注入 if (config != null) { addr = config.getValue("addr", addr); @@ -76,223 +104,248 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer } // 设置第一个启动的 实例为主实例 - /*if (isFirst) { - isMain = true; - isFirst = false; - }*/ if (!mainHub.containsKey(addr)) { // 确保同步执行此 init 逻辑 mainHub.put(addr, this); } - if (!initSocket(0)) { - return; - } - // 消息 事件接收 - new Thread(() -> { - while (true) { - try { - String readLine = reader.readLine(); - if (readLine == null && initSocket(Integer.MAX_VALUE)) { // 连接中断 处理 - continue; - } + CompletableFuture.runAsync(() -> { + // 消息 事件接收 + new Thread(() -> { + if (!initSocket(0)) { + return; + } - String type = ""; - - // +ping - if ("+ping".equals(readLine)) { - send("+pong"); - continue; - } - - // 主题订阅消息 - if ("*3".equals(readLine)) { - readLine = reader.readLine(); // $7 len() - type = reader.readLine(); // message - if (!"message".equals(type)) { + while (true) { + try { + String readLine = reader.readLine(); + if (readLine == null && initSocket(Integer.MAX_VALUE)) { // 连接中断 处理 continue; } - reader.readLine(); //$n len(key) - String topic = reader.readLine(); // topic - String lenStr = reader.readLine();//$n len(value) - int clen = 0; - if (lenStr.startsWith("$")) { - clen = Integer.parseInt(lenStr.replace("$", "")); + String type = ""; + + // +ping + if ("+ping".equals(readLine)) { + send("+pong"); + continue; } - String value = ""; - do { - if (value.length() > 0) { - value += "\r\n"; + // 主题订阅消息 + if ("*3".equals(readLine)) { + readLine = reader.readLine(); // $7 len() + type = reader.readLine(); // message + if (!"message".equals(type)) { + continue; } - String s = reader.readLine(); - value += s; // value - } while (clen > 0 && clen > strLength(value)); + reader.readLine(); //$n len(key) + String topic = reader.readLine(); // topic - logger.finest("topic[" + topic + "]: " + value); + String lenStr = reader.readLine();//$n len(value) + int clen = 0; + if (lenStr.startsWith("$")) { + clen = Integer.parseInt(lenStr.replace("$", "")); + } - // lock msg - if ("lock".equals(topic)) { - Lock lock = lockTag.get(value); - if (lock != null) { - synchronized (lock) { - lock.notifyAll(); + String value = ""; + do { + if (value.length() > 0) { + value += "\r\n"; } + String s = reader.readLine(); + value += s; // value + } while (clen > 0 && clen > strLength(value)); + + logger.finest("topic[" + topic + "]: " + value); + + // lock msg + if ("lock".equals(topic)) { + Lock lock = lockTag.get(value); + if (lock != null) { + synchronized (lock) { + lock.notifyAll(); + } + } + continue; } - continue; - } - // rpc back msg - if (APP_NAME.equals(topic)) { - rpcBackQueue.add(Event.of(topic, value)); + // rpc back msg + if (APP_NAME.equals(topic)) { + rpcBackQueue.add(Event.of(topic, value)); + continue; + } + + // rpc call msg + if (rpcTopics.contains(topic)) { + rpcCallQueue.add(Event.of(topic, value)); + continue; + } + + // oth msg + topicQueue.add(Event.of(topic, value)); continue; } - // rpc call msg - if (rpcTopics.contains(topic)) { - rpcCallQueue.add(Event.of(topic, value)); + // timer 消息 + if ("*2".equals(readLine)) { + readLine = reader.readLine(); // $7 len() + type = reader.readLine(); // message + if (!"timer".equals(type)) { + continue; + } + reader.readLine(); //$n len(key) + String topic = reader.readLine(); // name + + logger.finest("timer[" + topic + "]: "); + timerQueue.add(timerMap.get(topic)); continue; } - // oth msg - topicQueue.add(Event.of(topic, value)); - continue; + logger.finest(readLine); + } catch (IOException e) { + if (e instanceof SocketException) { + initSocket(Integer.MAX_VALUE); + } + e.printStackTrace(); } + } + }).start(); + }).thenAcceptAsync(x -> { + // 定时调度事件,已加入耗时监控 + new Thread(() -> { + ExecutorService pool = Executors.newFixedThreadPool(1); + while (true) { + Timer timer = null; + try { + if ((timer = timerQueue.take()) == null) { + return; + } + long start = System.currentTimeMillis(); + pool.submit(timer.runnable).get(5, TimeUnit.SECONDS); + long end = System.currentTimeMillis(); + logger.finest(String.format("timer [%s] : elapsed time %s ms", timer.name, end - start)); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (TimeoutException e) { + logger.log(Level.SEVERE, "timer [" + timer.name + "] time out: " + 5 + " S", e); + pool = Executors.newFixedThreadPool(1); + } catch (Exception e) { + logger.log(Level.WARNING, "timer [" + timer.name + "]", e); + } + } + }).start(); - // timer 消息 - if ("*2".equals(readLine)) { - readLine = reader.readLine(); // $7 len() - type = reader.readLine(); // message - if (!"timer".equals(type)) { + // topic msg,已加入耗时监控 + new Thread(() -> { + ExecutorService pool = Executors.newFixedThreadPool(1); + while (true) { + Event event = null; + try { + if ((event = topicQueue.take()) == null) { continue; } - reader.readLine(); //$n len(key) - String topic = reader.readLine(); // name - logger.finest("timer[" + topic + "]: "); - timerQueue.add(timerMap.get(topic)); - continue; + String topic = event.topic; + String value = event.value; + pool.submit(() -> accept(topic, value)).get(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (TimeoutException e) { + logger.log(Level.SEVERE, "topic[" + event.topic + "] event deal time out: " + 5 + " S, value: " + event.value, e); + pool = Executors.newFixedThreadPool(1); + } catch (Exception e) { + logger.log(Level.WARNING, "topic[" + event.topic + "] event accept error :" + event.value, e); } - - logger.finest(readLine); - } catch (IOException e) { - if (e instanceof SocketException) { - initSocket(Integer.MAX_VALUE); - } - e.printStackTrace(); } - } - }).start(); + }).start(); - // 定时调度事件,已加入耗时监控 - new Thread(() -> { - ExecutorService pool = Executors.newFixedThreadPool(1); - while (true) { - Timer timer = null; - try { - if ((timer = timerQueue.take()) == null) { - return; + // rpc back ,仅做数据解析,暂无耗时监控 + new Thread(() -> { + while (true) { + Event event = null; + try { + if ((event = rpcBackQueue.take()) == null) { + continue; + } + //if (event) + logger.finest(String.format("rpc-back:[%s]: %s", event.topic, event.value)); + rpcAccept(event.value); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (Exception e) { + logger.log(Level.WARNING, "rpc-back[" + event.topic + "] event accept error :" + event.value, e); } - long start = System.currentTimeMillis(); - pool.submit(timer.runnable).get(5, TimeUnit.SECONDS); - long end = System.currentTimeMillis(); - logger.finest(String.format("timer [%s] : elapsed time %s ms", timer.name, end - start)); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (TimeoutException e) { - logger.log(Level.SEVERE, "timer [" + timer.name + "] time out: " + 5 + " S", e); - pool = Executors.newFixedThreadPool(1); - } catch (Exception e) { - logger.log(Level.WARNING, "timer [" + timer.name + "]", e); } - } - }).start(); + }).start(); - // topic msg,已加入耗时监控 - new Thread(() -> { - ExecutorService pool = Executors.newFixedThreadPool(1); - while (true) { - Event event = null; - try { - if ((event = topicQueue.take()) == null) { - continue; + // rpc call,已加入耗时监控 + new Thread(() -> { + ExecutorService pool = Executors.newFixedThreadPool(1); + while (true) { + Event event = null; + try { + if ((event = rpcCallQueue.take()) == null) { + continue; + } + logger.finest(String.format("rpc-call:[%s] %s", event.topic, event.value)); + String topic = event.topic; + String value = event.value; + pool.submit(() -> accept(topic, value)).get(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (TimeoutException e) { + logger.log(Level.SEVERE, "topic[" + event.topic + "] event deal time out: " + 5 + " S, value: " + event.value, e); + pool = Executors.newFixedThreadPool(1); + } catch (Exception e) { + logger.log(Level.WARNING, "rpc-call[" + event.topic + "] event accept error :" + event.value, e); } - - String topic = event.topic; - String value = event.value; - pool.submit(() -> accept(topic, value)).get(5, TimeUnit.SECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (TimeoutException e) { - logger.log(Level.SEVERE, "topic[" + event.topic + "] event deal time out: " + 5 + " S, value: " + event.value, e); - pool = Executors.newFixedThreadPool(1); - } catch (Exception e) { - logger.log(Level.WARNING, "topic[" + event.topic + "] event accept error :" + event.value, e); } - } - }).start(); + }).start(); - // rpc back ,仅做数据解析,暂无耗时监控 - new Thread(() -> { - while (true) { - Event event = null; - try { - if ((event = rpcBackQueue.take()) == null) { - continue; + // send msg + new Thread(() -> { + while (true) { + String msg = null; + try { + if ((msg = sendMsgQueue.take()) == null) { + continue; + } + // logger.log(Level.FINEST, "send-msg: [" + msg + "]"); + writer.write(msg.getBytes()); + writer.flush(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (Exception e) { + logger.log(Level.WARNING, "send-msg[" + msg + "] event accept error :", e); } - //if (event) - logger.finest(String.format("rpc-back:[%s]: %s", event.topic, event.value)); - rpcAccept(event.value); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (Exception e) { - logger.log(Level.WARNING, "rpc-back[" + event.topic + "] event accept error :" + event.value, e); } - } - }).start(); + }).start(); + }); - // rpc call,已加入耗时监控 - new Thread(() -> { - ExecutorService pool = Executors.newFixedThreadPool(1); - while (true) { - Event event = null; - try { - if ((event = rpcCallQueue.take()) == null) { - continue; - } - logger.finest(String.format("rpc-call:[%s] %s", event.topic, event.value)); - String topic = event.topic; - String value = event.value; - pool.submit(() -> accept(topic, value)).get(5, TimeUnit.SECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (TimeoutException e) { - logger.log(Level.SEVERE, "topic[" + event.topic + "] event deal time out: " + 5 + " S, value: " + event.value, e); - pool = Executors.newFixedThreadPool(1); - } catch (Exception e) { - logger.log(Level.WARNING, "rpc-call[" + event.topic + "] event accept error :" + event.value, e); - } - } - }).start(); + return this; + } - // send msg - new Thread(() -> { - while (true) { - String msg = null; - try { - if ((msg = sendMsgQueue.take()) == null) { - continue; - } - // logger.log(Level.FINEST, "send-msg: [" + msg + "]"); - writer.write(msg.getBytes()); - writer.flush(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (Exception e) { - logger.log(Level.WARNING, "send-msg[" + msg + "] event accept error :", e); - } - } - }).start(); + public boolean acceptsConf(AnyValue config) { + if (config == null) { + return false; + } + if (!getNodes(config).isEmpty()) { + return true; + } + return false; + } + + private HashMap getNodes(AnyValue config) { + AnyValue[] zhubs = config.getAnyValues("zhub"); + HashMap confMap = new HashMap<>(); + + for (AnyValue zhub : zhubs) { + String[] names = zhub.getNames(); + for (String name : names) { + confMap.put(name, zhub.getAnyValue(name)); + } + } + + return confMap; } // --------------------- @@ -370,8 +423,6 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer send("groupid " + groupid); StringBuffer buf = new StringBuffer("subscribe lock"); - /*if (isMain) { - }*/ if (mainHub.containsValue(this)) { buf.append(" " + APP_NAME); } @@ -582,7 +633,7 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer return; } - RpcResult rpcResult = rpc.buildResp(505, "请求超时"); + RpcResult rpcResult = rpc.render(505, "请求超时"); rpc.setRpcResult(rpcResult); logger.warning("rpc timeout: " + convert.convertTo(rpc)); rpc.notify(); @@ -595,7 +646,7 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer } catch (InterruptedException e) { e.printStackTrace(); // call error - RpcResult rpcResult = rpc.buildResp(501, "请求失败"); + RpcResult rpcResult = rpc.render(501, "请求失败"); rpc.setRpcResult(rpcResult); } return rpc.getRpcResult(); @@ -666,7 +717,7 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer publish(rpc.getBackTopic(), result); } catch (Exception e) { logger.log(Level.WARNING, "rpc call consumer error: " + v, e); - publish(rpc.getBackTopic(), rpc.buildError("服务调用失败!")); + publish(rpc.getBackTopic(), rpc.retError("服务调用失败!")); } // back }; diff --git a/src/main/java/org/redkalex/cache/redis/AbstractRedisSource.java b/src/main/java/org/redkalex/cache/redis/AbstractRedisSource.java new file mode 100644 index 0000000..53b9398 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/AbstractRedisSource.java @@ -0,0 +1,131 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package org.redkalex.cache.redis; + +import org.redkale.annotation.Resource; +import org.redkale.convert.Convert; +import org.redkale.convert.json.JsonConvert; +import org.redkale.source.AbstractCacheSource; +import org.redkale.util.AnyValue; +import org.redkale.util.RedkaleClassLoader; +import org.redkale.util.RedkaleException; +import org.redkale.util.ResourceFactory; + +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; + +/** + * @author zhangjx + * @since 2.8.0 + */ +public abstract class AbstractRedisSource extends AbstractCacheSource { + + public static final String CACHE_SOURCE_CRYPTOR = "cryptor"; + + protected String name; + + @Resource(required = false) + protected ResourceFactory resourceFactory; + + @Resource(required = false) + protected JsonConvert defaultConvert; + + @Resource(name = "$_convert", required = false) + protected JsonConvert convert; + + protected int db; + + protected RedisCryptor cryptor; + + protected AnyValue config; + + @Override + public void init(AnyValue conf) { + this.config = conf; + super.init(conf); + this.name = conf.getValue("name", ""); + if (this.convert == null) this.convert = this.defaultConvert; + if (conf != null) { + String cryptStr = conf.getValue(CACHE_SOURCE_CRYPTOR, "").trim(); + if (!cryptStr.isEmpty()) { + try { + Class cryptClass = (Class) getClass().getClassLoader().loadClass(cryptStr); + RedkaleClassLoader.putReflectionPublicConstructors(cryptClass, cryptClass.getName()); + this.cryptor = cryptClass.getConstructor().newInstance(); + } catch (ReflectiveOperationException e) { + throw new RedkaleException(e); + } + } + } + if (cryptor != null) { + if (resourceFactory != null) { + resourceFactory.inject(cryptor); + } + cryptor.init(conf); + } + } + + @Override + public void destroy(AnyValue conf) { + super.destroy(conf); + if (cryptor != null) { + cryptor.destroy(conf); + } + } + + @Override + public void close() throws Exception { //在 Application 关闭时调用 + destroy(null); + } + + @Override + public String resourceName() { + return name; + } + + protected String decryptValue(String key, RedisCryptor cryptor, String value) { + return cryptor != null ? cryptor.decrypt(key, value) : value; + } + + protected T decryptValue(String key, RedisCryptor cryptor, Type type, byte[] bs) { + return decryptValue(key, cryptor, convert, type, bs); + } + + protected T decryptValue(String key, RedisCryptor cryptor, Convert c, Type type, byte[] bs) { + if (bs == null) return null; + if (type == byte[].class) return (T) bs; + if (cryptor == null || (type instanceof Class && (((Class) type).isPrimitive() || Number.class.isAssignableFrom((Class) type)))) { + return (T) (c == null ? this.convert : c).convertFrom(type, bs); + } + String deval = cryptor.decrypt(key, new String(bs, StandardCharsets.UTF_8)); + return deval == null ? null : (T) (c == null ? this.convert : c).convertFrom(type, deval.getBytes(StandardCharsets.UTF_8)); + } + + protected String encryptValue(String key, RedisCryptor cryptor, String value) { + return cryptor != null ? cryptor.encrypt(key, value) : value; + } + + protected byte[] encryptValue(String key, RedisCryptor cryptor, Convert c, T value) { + return encryptValue(key, cryptor, null, c, value); + } + + protected byte[] encryptValue(String key, RedisCryptor cryptor, Type type, Convert c, T value) { + if (value == null) return null; + Type t = type == null ? value.getClass() : type; + if (cryptor == null && type == String.class) { + return value.toString().getBytes(StandardCharsets.UTF_8); + } + return encryptValue(key, cryptor, t, (c == null ? this.convert : c).convertToBytes(t, value)); + } + + protected byte[] encryptValue(String key, RedisCryptor cryptor, Type type, byte[] bs) { + if (bs == null) return null; + if (cryptor == null || (type instanceof Class && (((Class) type).isPrimitive() || Number.class.isAssignableFrom((Class) type)))) { + return bs; + } + String enval = cryptor.encrypt(key, new String(bs, StandardCharsets.UTF_8)); + return enval == null ? null : enval.getBytes(StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/org/redkalex/cache/redis/MyRedisCacheSource.java b/src/main/java/org/redkalex/cache/redis/MyRedisCacheSource.java new file mode 100644 index 0000000..493c350 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/MyRedisCacheSource.java @@ -0,0 +1,343 @@ +package org.redkalex.cache.redis; + +import org.redkale.annotation.AutoLoad; +import org.redkale.annotation.ResourceType; +import org.redkale.service.Local; +import org.redkale.source.CacheSource; +import org.redkale.util.AnyValue; + +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +@Local +@AutoLoad(false) +@ResourceType(CacheSource.class) +public class MyRedisCacheSource extends RedisCacheSource { + + @Override + public void init(AnyValue conf) { + super.init(conf); + } +/* +//--------------------- zset ------------------------------ + + public int getZrank(String key, V v) { + byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); + Long t = (Long) send("ZRANK", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); + + return t == null ? -1 : (int) (long) t; + } + + public int getZrevrank(String key, V v) { + byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); + Long t = (Long) send("ZREVRANK", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); + + return t == null ? -1 : (int) (long) t; + } + + //ZRANGE/ZREVRANGE key start stop + public List getZset(String key) { + byte[][] bytes = Stream.of(key, 0, -1).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); + List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); + List vs2 = new ArrayList(vs.size()); + + for (int i = 0; i < vs.size(); ++i) { + if (i % 2 == 1) { + vs2.add(this.convert.convertFrom(this.objValueType, String.valueOf(vs.get(i)))); + } else { + vs2.add(vs.get(i)); + } + } + + return vs2; + } + + public List getZset(String key, int offset, int limit) { + byte[][] bytes = Stream.of(key, offset, offset + limit - 1).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); + List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); + List vs2 = new ArrayList(vs.size()); + + for (int i = 0; i < vs.size(); ++i) { + if (i % 2 == 1) { + vs2.add(this.convert.convertFrom(this.objValueType, String.valueOf(vs.get(i)))); + } else { + vs2.add(vs.get(i)); + } + } + + return vs2; + } + + public LinkedHashMap getZsetLongScore(String key) { + LinkedHashMap map = getZsetDoubleScore(key); + if (map.isEmpty()) { + return new LinkedHashMap<>(); + } + + LinkedHashMap map2 = new LinkedHashMap<>(map.size()); + map.forEach((k, v) -> map2.put(k, (long) (double) v)); + return map2; + } + + public LinkedHashMap getZsetItemsLongScore(String key) { + byte[][] bytes = Stream.of(key, 0, -1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); + List vs = (List) send("ZRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); + + LinkedHashMap map = new LinkedHashMap<>(); + for (int i = 0; i < vs.size(); i += 2) { + map.put((V) vs.get(i), (long) Double.parseDouble((String) vs.get(i + 1))); + } + return map; + } + + public Long getZsetLongScore(String key, V v) { + Double score = getZsetDoubleScore(key, v); + if (score == null) { + return null; + } + return (long) (double) score; + } + + public LinkedHashMap getZsetDoubleScore(String key) { + byte[][] bytes = Stream.of(key, 0, -1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); + List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); + + LinkedHashMap map = new LinkedHashMap<>(); + for (int i = 0; i < vs.size(); i += 2) { + map.put((V) vs.get(i), Double.parseDouble((String) vs.get(i + 1))); + } + return map; + } + + public Double getZsetDoubleScore(String key, V v) { + byte[][] bytes = Stream.of(key, v).map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); + Serializable zscore = send("ZSCORE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); + if (zscore == null) { + return null; + } + + return Double.parseDouble(String.valueOf(zscore)); + } + + public LinkedHashMap getZsetLongScore(String key, int offset, int limit) { + byte[][] bytes = Stream.of(key, offset, offset + limit - 1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); + List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); + + LinkedHashMap map = new LinkedHashMap<>(); + for (int i = 0; i < vs.size(); i += 2) { + map.put((V) vs.get(i), (long) Double.parseDouble((String) vs.get(i + 1))); + } + return map; + } + + public LinkedHashMap getZsetDoubleScore(String key, int offset, int limit) { + byte[][] bytes = Stream.of(key, offset, offset + limit - 1, "WITHSCORES").map(x -> String.valueOf(x).getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new); + List vs = (List) send("ZREVRANGE", CacheEntryType.OBJECT, (Type) null, key, bytes).join(); + + LinkedHashMap map = new LinkedHashMap<>(); + for (int i = 0; i < vs.size(); i += 2) { + map.put((V) vs.get(i), Double.parseDouble(vs.get(i + 1) + "")); + } + return map; + } +* */ + + // -------------------- + public void zadd(String key, Map kv) { + if (kv == null || kv.isEmpty()) { + return; + } + List args = new ArrayList(); + kv.forEach((k, v) -> { + args.add(k); + args.add(v); + }); + + sendAsync("ZADD", key, args.toArray(Serializable[]::new)).join(); + } + + public double zincr(String key, Serializable number, N n) { + return sendAsync("ZINCRBY", key, number, n).thenApply(x -> x.getDoubleValue(0d)).join(); + } + + public void zrem(String key, Serializable... vs) { + sendAsync("ZREM", key, vs).join(); + } + + /*public List zexists(String key, T... fields) { + if (fields == null || fields.length == 0) { + return new ArrayList<>(); + } + List para = new ArrayList<>(); + para.add("" + + " local key = KEYS[1];" + + " local args = ARGV;" + + " local result = {};" + + " for i,v in ipairs(args) do" + + " local inx = redis.call('ZREVRANK', key, v);" + + " if(inx) then" + + " table.insert(result,1,v);" + + " end" + + " end" + + " return result;"); + para.add("1"); + para.add(key); + for (Object field : fields) { + para.add(String.valueOf(field)); + } + + // todo: + //sendAsync("EVAL", null, para.toArray(Serializable[]::new)).thenApply(x -> x.).join(); + + return null; + }*/ + + //--------------------- bit ------------------------------ + public boolean getBit(String key, int offset) { + return sendAsync("GETBIT", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(offset).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getIntValue(0) > 0).join(); + } + + public void setBit(String key, int offset, boolean bool) { + sendAsync("SETBIT", key, offset, bool ? 1 : 0).join(); + } + //--------------------- bit ------------------------------ + + //--------------------- lock ------------------------------ + // 尝试加锁,成功返回0,否则返回上一锁剩余毫秒值 + public long tryLock(String key, int millis) { + Serializable[] obj = {"" + + "if (redis.call('EXISTS',KEYS[1]) == 0) then " + + "redis.call('PSETEX',KEYS[1],ARGV[1],1); " + + "return 0; " + + "else " + + "return redis.call('PTTL',KEYS[1]); " + + "end;", 1, key, millis + }; + + return sendAsync("EVAL", null, obj).thenApply(v -> v.getIntValue(1)).join(); + } + + // 加锁 + public void lock(String key, int millis) { + long i; + do { + i = tryLock(key, millis); + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } while (i > 0); + } + + // 解锁 + public void unlock(String key) { + remove(key); + } + + //--------------------- key ------------------------------ + + public String get(String key) { + return get(key, String.class); + } + + public void set(String key, Serializable value) { + sendAsync("SET", key, value).join(); + } + + //--------------------- set ------------------------------ + public void sadd(String key, Collection args) { + saddAsync(key, args.toArray(Serializable[]::new)).join(); + } + + public void sadd(String key, Serializable... args) { + saddAsync(key, Arrays.stream(args).toArray(Serializable[]::new)).join(); + } + + public void srem(String key, Serializable... args) { + sremAsync(key, args).join(); + } + + public CompletableFuture saddAsync(String key, Serializable... args) { + return sendAsync("SADD", key, args); + } + + public CompletableFuture sremAsync(String key, Serializable... args) { + return sendAsync("SREM", key, args); + } + + //--------------------- hm ------------------------------ + + /*public Long incrHm(String key, String field, int value) { + return sendAsync("HINCRBY", key, field, value).thenApply(x -> x.getLongValue(0l)).join(); + } + + public Double incrHm(String key, String field, double value) { + return sendAsync("HINCRBYFLOAT", key, field, value).thenApply(x -> x.getDoubleValue(0d)).join(); + }*/ + + public void setHm(String key, String field, Serializable value) { + setHmsAsync(key, Map.of(field, value)).join(); + } + + public void setHms(String key, Map kv) { + setHmsAsync(key, kv).join(); + } + + public CompletableFuture setHmsAsync(String key, Map kv) { + List args = new ArrayList(); + kv.forEach((k, v) -> { + args.add(k); + args.add(v); + }); + + return sendAsync("HMSET", key, args.toArray(Serializable[]::new)); + } + + public String getHm(String key, String field) { + return getHm(key, String.class, field); + } + + public T getHm(String key, Class type, String field) { + List list = super.hmget(key, type, field); + if (list == null && list.isEmpty()) { + return null; + } + return (T) list.get(0); + } + + public Map getHms(String key, String... field) { + return getHms(key, String.class, field); + } + + public Map getHms(String key, Class type, String... field) { + List list = super.hmget(key, type, field); + if (list == null && list.isEmpty()) { + return null; + } + Map map = new HashMap<>(field.length); + + for (int i = 0; i < field.length; i++) { + if (list.get(i) == null) { + continue; + } + map.put(field[i], (T) list.get(i)); + } + return map; + } + + /*public Map getHmall(String key) { + List list = null; // TODO: + Map map = new HashMap<>(); + if (list.isEmpty()) { + return map; + } + + for (int i = 0; i + 1 < list.size(); i += 2) { + map.put((String) list.get(i), list.get(i + 1)); + } + return map; + }*/ +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCRC16.java b/src/main/java/org/redkalex/cache/redis/RedisCRC16.java new file mode 100644 index 0000000..2c0d38f --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCRC16.java @@ -0,0 +1,78 @@ +/* + * + */ +package org.redkalex.cache.redis; + +import org.redkale.util.Utility; + +import java.util.Arrays; + +/** + * @author zhangjx + */ +public class RedisCRC16 { + + private static final int[] LOOKUP_TABLE = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, + 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, + 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, + 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, + 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, + 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, + 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, + 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, + 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, + 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, + 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, + 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, + 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, + 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, + 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, + 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, + 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, + 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, + 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, + 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, + 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, + 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; + + private RedisCRC16() { + } + + public static int crc16(byte[] bytes) { + int crc = 0x0000; + for (byte b : bytes) { + crc = (crc << 8) ^ LOOKUP_TABLE[((crc >>> 8) ^ (b & 0xFF)) & 0xFF]; + } + return crc & 0xFFFF; + } + + public static int calcSlot(int maxSlot, byte[] key) { + if (key == null) { + return 0; + } + int start = Utility.indexOf(key, (byte) '{'); + if (start != -1) { + int end = Utility.indexOf(key, start + 1, (byte) '}'); + if (end != -1) { + key = Arrays.copyOfRange(key, start + 1, end); + } + } + int result = crc16(key) % maxSlot; + return result; + } + + public static int calcSlot(int maxSlot, String key) { + if (key == null) { + return 0; + } + int start = key.indexOf('{'); + if (start != -1) { + int end = key.indexOf('}'); + if (end != -1 && start + 1 < end) { + key = key.substring(start + 1, end); + } + } + int result = crc16(key.getBytes()) % maxSlot; + return result; + } +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheClient.java b/src/main/java/org/redkalex/cache/redis/RedisCacheClient.java new file mode 100644 index 0000000..3bdca16 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheClient.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.net.AsyncConnection; +import org.redkale.net.AsyncGroup; +import org.redkale.net.client.Client; +import org.redkale.net.client.ClientAddress; + +/** + * @author zhangjx + */ +public class RedisCacheClient extends Client { + + public RedisCacheClient(String name, AsyncGroup group, String key, ClientAddress address, int maxConns, int maxPipelines, RedisCacheReqAuth authReq, RedisCacheReqDB dbReq) { + super(name, group, true, address, maxConns, maxPipelines, () -> new RedisCacheReqPing(), () -> new RedisCacheReqClose(), null); //maxConns + if (authReq != null || dbReq != null) { + if (authReq != null && dbReq != null) { + this.authenticate = conn -> writeChannel(conn, authReq).thenCompose(v -> writeChannel(conn, dbReq)).thenApply(v -> conn); + } else if (authReq != null) { + this.authenticate = conn -> writeChannel(conn, authReq).thenApply(v -> conn); + } else { + this.authenticate = conn -> writeChannel(conn, dbReq).thenApply(v -> conn); + } + } + } + + @Override + protected RedisCacheConnection createClientConnection(final int index, AsyncConnection channel) { + return new RedisCacheConnection(this, index, channel); + } + +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheCodec.java b/src/main/java/org/redkalex/cache/redis/RedisCacheCodec.java new file mode 100644 index 0000000..41902c7 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheCodec.java @@ -0,0 +1,249 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.net.client.ClientCodec; +import org.redkale.net.client.ClientConnection; +import org.redkale.util.ByteArray; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +/** + * @author zhangjx + */ +public class RedisCacheCodec extends ClientCodec { + + protected static final byte TYPE_STRING = '+'; //简单字符串(不包含CRLF)类型 + + protected static final byte TYPE_ERROR = '-'; //错误(不包含CRLF)类型 + + protected static final byte TYPE_NUMBER = ':'; //整型 + + protected static final byte TYPE_BULK = '$'; //块字符串 + + protected static final byte TYPE_ARRAY = '*'; //数组 + + protected static final Logger logger = Logger.getLogger(RedisCacheCodec.class.getSimpleName()); + + protected byte halfFrameCmd; + + protected int halfFrameBulkLength = -10; + + protected int halfFrameArraySize = -10; + + protected int halfFrameArrayIndex; //从0开始 + + protected int halfFrameArrayItemLength = -10; + + protected ByteArray halfFrameBytes; + + protected byte frameType; + + protected byte[] frameValue; //(不包含CRLF) + + protected List frameList; //(不包含CRLF) + + private ByteArray recyclableArray; + + public RedisCacheCodec(ClientConnection connection) { + super(connection); + } + + protected ByteArray pollArray(ByteArray array) { + if (recyclableArray == null) { + recyclableArray = new ByteArray(); + } else { + recyclableArray.clear(); + } + recyclableArray.clear(); + if (array != null) { + recyclableArray.put(array, 0, array.length()); + } + return recyclableArray; + } + + private boolean checkBytesFrame(RedisCacheConnection conn, ByteBuffer buffer, ByteArray array) { +// byte[] dbs = new byte[buffer.remaining()]; +// for (int i = 0; i < dbs.length; i++) { +// dbs[i] = buffer.get(buffer.position() + i); +// } +// ArrayDeque deque = (ArrayDeque) responseQueue(conn); +// logger.log(Level.FINEST, "[" + Utility.nowMillis() + "] [" + Thread.currentThread().getName() + "]: " + conn + ", 原始数据: " + new String(dbs).replace("\r\n", " ") + ", req=" + deque.getFirst().getRequest()); + + array.clear(); + byte type = halfFrameCmd == 0 ? buffer.get() : halfFrameCmd; + if (halfFrameBytes != null) { + array.put(halfFrameBytes, 0, halfFrameBytes.length()); + } + frameType = type; + if (type == TYPE_STRING || type == TYPE_ERROR || type == TYPE_NUMBER) { + if (readComplete(buffer, array)) { + frameValue = array.getBytes(); + } else { + halfFrameCmd = type; + halfFrameBytes = pollArray(array); + return false; + } + } else if (type == TYPE_BULK) { + int bulkLength = halfFrameBulkLength; + if (bulkLength < -2) { + if (!readComplete(buffer, array)) { //没有读到bulkLength + halfFrameCmd = type; + halfFrameBulkLength = -10; + halfFrameBytes = pollArray(array); + return false; + } + bulkLength = Integer.parseInt(array.toString(StandardCharsets.UTF_8)); + array.clear(); + } + if (bulkLength == -1) { + frameValue = null; + } else if (readComplete(buffer, array)) { + frameValue = array.getBytes(); + } else { + halfFrameCmd = type; + halfFrameBulkLength = bulkLength; + halfFrameBytes = pollArray(array); + return false; + } + } else if (type == TYPE_ARRAY) { + int arraySize = halfFrameArraySize; + if (arraySize < -2) { + if (!readComplete(buffer, array)) { //没有读到arraySize + halfFrameCmd = type; + halfFrameArraySize = -10; + halfFrameArrayIndex = 0; + halfFrameArrayItemLength = -10; + halfFrameBytes = pollArray(array); + return false; + } + arraySize = Integer.parseInt(array.toString(StandardCharsets.UTF_8)); + array.clear(); + } + int arrayIndex = halfFrameArrayIndex; + for (int i = arrayIndex; i < arraySize; i++) { + int itemLength = halfFrameArrayItemLength; + halfFrameArrayItemLength = -10; + if (itemLength < -2) { + if (!readComplete(buffer, array)) { //没有读到bulkLength + halfFrameCmd = type; + halfFrameArraySize = arraySize; + halfFrameArrayIndex = i; + halfFrameArrayItemLength = -10; + halfFrameBytes = pollArray(array); + return false; + } + byte sign = array.get(0); + itemLength = Integer.parseInt(array.toString(1, StandardCharsets.UTF_8)); + array.clear(); + if (sign == TYPE_ARRAY) { //数组中嵌套数组,目前有 HSCAN + frameValue = null; + if (frameList != null) { + frameList.clear(); + } + clearHalfFrame(); + if (itemLength == 0) { + return true; + } + halfFrameCmd = sign; + halfFrameArraySize = itemLength; + if (!buffer.hasRemaining()) { + return false; + } + return checkBytesFrame(conn, buffer, array); + } + } + int cha = itemLength - array.length(); + if (itemLength == -1) { + if (frameList == null) { + frameList = new ArrayList<>(); + } + frameList.add(null); + array.clear(); + } else if (buffer.remaining() >= cha + 2) { + for (int j = 0; j < cha; j++) array.put(buffer.get()); + buffer.get(); //\r + buffer.get(); //\n + if (frameList == null) { + frameList = new ArrayList<>(); + } + frameList.add(array.getBytes()); + array.clear(); + } else { + while (buffer.hasRemaining()) array.put(buffer.get()); + halfFrameCmd = type; + halfFrameArraySize = arraySize; + halfFrameArrayIndex = i; + halfFrameArrayItemLength = itemLength; + halfFrameBytes = pollArray(array); + return false; + } + } + } + clearHalfFrame(); + return true; + } + + protected void clearHalfFrame() { + halfFrameCmd = 0; + halfFrameBulkLength = -10; + halfFrameArraySize = -10; + halfFrameArrayIndex = 0; + halfFrameArrayItemLength = -10; + halfFrameBytes = null; + } + + @Override + public void decodeMessages(ByteBuffer realbuf, ByteArray array) { + RedisCacheConnection conn = (RedisCacheConnection) connection; + if (!realbuf.hasRemaining()) { + return; + } + ByteBuffer buffer = realbuf; + if (!checkBytesFrame(conn, buffer, array)) { + return; + } + //buffer必然包含一个完整的frame数据 + boolean first = true; + RedisCacheRequest request = null; + while (first || buffer.hasRemaining()) { + if (request == null) { + request = nextRequest(); + } + if (!first && !checkBytesFrame(conn, buffer, array)) { + break; + } + if (frameType == TYPE_ERROR) { + addMessage(request, new RuntimeException(new String(frameValue, StandardCharsets.UTF_8))); + } else { + addMessage(request, conn.pollResultSet(request).prepare(frameType, frameValue, frameList)); + } + frameType = 0; + frameValue = null; + frameList = null; + halfFrameCmd = 0; + halfFrameBytes = null; + first = false; + buffer = realbuf; + } + } + + protected boolean readComplete(ByteBuffer buffer, ByteArray array) { + while (buffer.hasRemaining()) { + byte b = buffer.get(); + if (b == '\n') { + array.removeLastByte(); //移除 \r + return true; + } + array.put(b); + } + return false; + } +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheConnection.java b/src/main/java/org/redkalex/cache/redis/RedisCacheConnection.java new file mode 100644 index 0000000..8741e1b --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheConnection.java @@ -0,0 +1,49 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.net.AsyncConnection; +import org.redkale.net.WorkThread; +import org.redkale.net.client.Client; +import org.redkale.net.client.ClientCodec; +import org.redkale.net.client.ClientConnection; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +/** + * @author zhangjx + */ +public class RedisCacheConnection extends ClientConnection { + + public RedisCacheConnection(Client client, int index, AsyncConnection channel) { + super(client, index, channel); + } + + @Override + protected ClientCodec createCodec() { + return new RedisCacheCodec(this); + } + + protected CompletableFuture writeRequest(RedisCacheRequest request) { + return super.writeChannel(request); + } + + protected CompletableFuture writeRequest(RedisCacheRequest request, Function respTransfer) { + return super.writeChannel(request, respTransfer); + } + + public RedisCacheResult pollResultSet(RedisCacheRequest request) { + RedisCacheResult rs = new RedisCacheResult(); + return rs; + } + + public RedisCacheRequest pollRequest(WorkThread workThread) { + RedisCacheRequest rs = new RedisCacheRequest().currThread(workThread); + return rs; + } + +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheReqAuth.java b/src/main/java/org/redkalex/cache/redis/RedisCacheReqAuth.java new file mode 100644 index 0000000..41dbd2f --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheReqAuth.java @@ -0,0 +1,45 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.net.client.ClientConnection; +import org.redkale.util.ByteArray; + +import java.nio.charset.StandardCharsets; + +/** + * @author zhangjx + */ +public class RedisCacheReqAuth extends RedisCacheRequest { + + private static final byte[] PS = "AUTH".getBytes(StandardCharsets.UTF_8); + + protected String password; + + public RedisCacheReqAuth(String password) { + this.password = password; + } + + @Override + public void writeTo(ClientConnection conn, ByteArray writer) { + byte[] pwd = password.getBytes(); + writer.put((byte) '*'); + writer.put((byte) '2'); + writer.put((byte) '\r', (byte) '\n'); + writer.put((byte) '$'); + writer.put((byte) '4'); + writer.put((byte) '\r', (byte) '\n'); + writer.put(PS); + writer.put((byte) '\r', (byte) '\n'); + + writer.put((byte) '$'); + writer.put(String.valueOf(pwd.length).getBytes(StandardCharsets.UTF_8)); + writer.put((byte) '\r', (byte) '\n'); + writer.put(pwd); + writer.put((byte) '\r', (byte) '\n'); + + } +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheReqClose.java b/src/main/java/org/redkalex/cache/redis/RedisCacheReqClose.java new file mode 100644 index 0000000..67432f8 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheReqClose.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.net.client.ClientConnection; +import org.redkale.util.ByteArray; + +import java.nio.charset.StandardCharsets; + +/** + * @author zhangjx + */ +public class RedisCacheReqClose extends RedisCacheRequest { + + private static final byte[] PS = "QUIT".getBytes(StandardCharsets.UTF_8); + + @Override + public final boolean isCloseType() { + return true; + } + + @Override + public void writeTo(ClientConnection conn, ByteArray writer) { + writer.put((byte) '*'); + writer.put((byte) '1'); + writer.put((byte) '\r', (byte) '\n'); + writer.put((byte) '$'); + writer.put((byte) '4'); + writer.put((byte) '\r', (byte) '\n'); + writer.put(PS); + writer.put((byte) '\r', (byte) '\n'); + } +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheReqDB.java b/src/main/java/org/redkalex/cache/redis/RedisCacheReqDB.java new file mode 100644 index 0000000..37ef12a --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheReqDB.java @@ -0,0 +1,43 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.net.client.ClientConnection; +import org.redkale.util.ByteArray; + +import java.nio.charset.StandardCharsets; + +/** + * @author zhangjx + */ +public class RedisCacheReqDB extends RedisCacheRequest { + + protected int db; + + public RedisCacheReqDB(int db) { + this.db = db; + } + + @Override + public void writeTo(ClientConnection conn, ByteArray writer) { + writer.put((byte) '*'); + writer.put((byte) '2'); + writer.put((byte) '\r', (byte) '\n'); + writer.put((byte) '$'); + writer.put((byte) '6'); + writer.put((byte) '\r', (byte) '\n'); + writer.put("SELECT".getBytes(StandardCharsets.UTF_8)); + writer.put((byte) '\r', (byte) '\n'); + + byte[] dbs = String.valueOf(db).getBytes(StandardCharsets.UTF_8); + writer.put((byte) '$'); + writer.put(String.valueOf(dbs.length).getBytes(StandardCharsets.UTF_8)); + writer.put((byte) '\r', (byte) '\n'); + writer.put(dbs); + writer.put((byte) '\r', (byte) '\n'); + + } +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheReqPing.java b/src/main/java/org/redkalex/cache/redis/RedisCacheReqPing.java new file mode 100644 index 0000000..114bb10 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheReqPing.java @@ -0,0 +1,31 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.net.client.ClientConnection; +import org.redkale.util.ByteArray; + +import java.nio.charset.StandardCharsets; + +/** + * @author zhangjx + */ +public class RedisCacheReqPing extends RedisCacheRequest { + + private static final byte[] PS = "PING".getBytes(StandardCharsets.UTF_8); + + @Override + public void writeTo(ClientConnection conn, ByteArray writer) { + writer.put((byte) '*'); + writer.put((byte) '1'); + writer.put((byte) '\r', (byte) '\n'); + writer.put((byte) '$'); + writer.put((byte) '4'); + writer.put((byte) '\r', (byte) '\n'); + writer.put(PS); + writer.put((byte) '\r', (byte) '\n'); + } +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheRequest.java b/src/main/java/org/redkalex/cache/redis/RedisCacheRequest.java new file mode 100644 index 0000000..403b7a8 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheRequest.java @@ -0,0 +1,61 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.net.client.ClientConnection; +import org.redkale.net.client.ClientRequest; +import org.redkale.util.ByteArray; + +import java.nio.charset.StandardCharsets; + +/** + * @author zhangjx + */ +public class RedisCacheRequest extends ClientRequest { + + static final byte[] TRUE = new byte[]{'t'}; + + static final byte[] FALSE = new byte[]{'f'}; + + protected String key; + + protected String command; + + protected byte[][] args; + + public RedisCacheRequest prepare(String command, String key, byte[]... args) { + super.prepare(); + this.command = command; + this.key = key; + this.args = args; + return this; + } + + @Override + public void writeTo(ClientConnection conn, ByteArray writer) { + writer.put((byte) '*'); + writer.put(String.valueOf(args.length + 1).getBytes(StandardCharsets.UTF_8)); + writer.put((byte) '\r', (byte) '\n'); + writer.put((byte) '$'); + writer.put(String.valueOf(command.length()).getBytes(StandardCharsets.UTF_8)); + writer.put((byte) '\r', (byte) '\n'); + writer.put(command.getBytes(StandardCharsets.UTF_8)); + writer.put((byte) '\r', (byte) '\n'); + + for (final byte[] arg : args) { + writer.put((byte) '$'); + writer.put(String.valueOf(arg.length).getBytes(StandardCharsets.UTF_8)); + writer.put((byte) '\r', (byte) '\n'); + writer.put(arg); + writer.put((byte) '\r', (byte) '\n'); + } + } + + @Override + public String toString() { + return getClass().getSimpleName() + "{command=" + command + ", key=" + key + "}"; + } +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheResult.java b/src/main/java/org/redkalex/cache/redis/RedisCacheResult.java new file mode 100644 index 0000000..96e8445 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheResult.java @@ -0,0 +1,151 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.convert.json.JsonConvert; + +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.util.*; + +/** + * @author zhangjx + */ +public class RedisCacheResult { + + //+ 简单字符串类型 (不包含CRLF) + //- 错误类型 (不包含CRLF) + //': 整型 + //$ 块字符串 + //* 数组 + protected byte frameType; + + protected byte[] frameValue; //(不包含CRLF) + + protected List frameList; //(不包含CRLF) + + public RedisCacheResult prepare(byte byteType, byte[] val, List bytesList) { + this.frameType = byteType; + this.frameValue = val; + this.frameList = bytesList; + return this; + } + + public Void getVoidValue() { + return null; + } + + public byte[] getFrameValue() { + return frameValue; + } + + public Boolean getBoolValue() { + if (frameValue == null) { + return false; + } + String val = new String(frameValue, StandardCharsets.UTF_8); + if ("OK".equals(val)) { + return true; + } + return Integer.parseInt(val) > 0; + } + + public String getStringValue(String key, RedisCryptor cryptor) { + if (frameValue == null) { + return null; + } + String val = new String(frameValue, StandardCharsets.UTF_8); + if (cryptor != null) { + val = cryptor.decrypt(key, val); + } + return val; + } + + public Double getDoubleValue(Double defvalue) { + return frameValue == null ? defvalue : Double.parseDouble(new String(frameValue, StandardCharsets.UTF_8)); + } + + public Long getLongValue(Long defvalue) { + return frameValue == null ? defvalue : Long.parseLong(new String(frameValue, StandardCharsets.UTF_8)); + } + + public Integer getIntValue(Integer defvalue) { + return frameValue == null ? defvalue : Integer.parseInt(new String(frameValue, StandardCharsets.UTF_8)); + } + + public T getObjectValue(String key, RedisCryptor cryptor, Type type) { + return formatValue(key, cryptor, frameValue, type); + } + + protected Set getSetValue(String key, RedisCryptor cryptor, Type type) { + if (frameList == null || frameList.isEmpty()) { + return new LinkedHashSet<>(); + } + Set set = new LinkedHashSet<>(); + for (byte[] bs : frameList) { + set.add(formatValue(key, cryptor, bs, type)); + } + return set; + } + + protected List getListValue(String key, RedisCryptor cryptor, Type type) { + if (frameList == null || frameList.isEmpty()) { + return new ArrayList<>(); + } + List list = new ArrayList<>(); + for (byte[] bs : frameList) { + list.add(formatValue(key, cryptor, bs, type)); + } + return list; + } + + protected Map getMapValue(String key, RedisCryptor cryptor, Type type) { + if (frameList == null || frameList.isEmpty()) { + return new LinkedHashMap<>(); + } + Map map = new LinkedHashMap<>(); + for (int i = 0; i < frameList.size(); i += 2) { + byte[] bs1 = frameList.get(i); + byte[] bs2 = frameList.get(i + 1); + T val = formatValue(key, cryptor, bs2, type); + if (val != null) { + map.put(formatValue(key, cryptor, bs1, String.class).toString(), val); + } + } + return map; + } + + protected static T formatValue(String key, RedisCryptor cryptor, byte[] frames, Type type) { + if (frames == null) { + return null; + } + if (type == byte[].class) { + return (T) frames; + } + if (type == String.class) { + String val = new String(frames, StandardCharsets.UTF_8); + if (cryptor != null) { + val = cryptor.decrypt(key, val); + } + return (T) val; + } + if (type == boolean.class || type == Boolean.class) { + return (T) (Boolean) "t".equalsIgnoreCase(new String(frames, StandardCharsets.UTF_8)); + } + if (type == long.class || type == Long.class) { + return (T) (Long) Long.parseLong(new String(frames, StandardCharsets.UTF_8)); + } + if (type == double.class || type == Double.class) { + return (T) (Double) Double.parseDouble(new String(frames, StandardCharsets.UTF_8)); + } + if (cryptor != null) { + String val = cryptor.decrypt(key, new String(frames, StandardCharsets.UTF_8)); + return (T) JsonConvert.root().convertFrom(type, val); + } + return (T) JsonConvert.root().convertFrom(type, frames); + } + +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheSource.java b/src/main/java/org/redkalex/cache/redis/RedisCacheSource.java new file mode 100644 index 0000000..0e7211c --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheSource.java @@ -0,0 +1,1801 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.annotation.AutoLoad; +import org.redkale.annotation.Resource; +import org.redkale.annotation.ResourceListener; +import org.redkale.annotation.ResourceType; +import org.redkale.convert.Convert; +import org.redkale.convert.json.JsonConvert; +import org.redkale.net.AsyncGroup; +import org.redkale.net.WorkThread; +import org.redkale.net.client.ClientAddress; +import org.redkale.service.Local; +import org.redkale.source.CacheSource; +import org.redkale.util.*; + +import java.io.Serializable; +import java.lang.reflect.Type; +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Function; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static org.redkale.boot.Application.RESNAME_APP_CLIENT_ASYNCGROUP; +import static org.redkale.boot.Application.RESNAME_APP_EXECUTOR; + +/** + * 详情见: https://redkale.org + * + * @author zhangjx + */ +@Local +@AutoLoad(false) +@ResourceType(CacheSource.class) +public class RedisCacheSource extends AbstractRedisSource { + + static final boolean debug = false; //System.getProperty("os.name").contains("Window") || System.getProperty("os.name").contains("Mac"); + + protected static final byte FRAME_TYPE_BULK = '$'; //块字符串 + + protected static final byte FRAME_TYPE_ARRAY = '*'; //数组 + + protected static final byte FRAME_TYPE_STRING = '+'; //简单字符串(不包含CRLF)类型 + + protected static final byte FRAME_TYPE_ERROR = '-'; //错误(不包含CRLF)类型 + + protected static final byte FRAME_TYPE_NUMBER = ':'; //整型 + + protected static final byte[] NX = "NX".getBytes(); + + protected static final byte[] EX = "EX".getBytes(); + + private final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); + + @Resource(name = RESNAME_APP_CLIENT_ASYNCGROUP, required = false) + protected AsyncGroup clientAsyncGroup; + + //配置 APP_EXECUTOR资源为null + @Resource(name = RESNAME_APP_EXECUTOR, required = false) + protected ExecutorService workExecutor; + + protected RedisCacheClient client; + + protected InetSocketAddress address; + + @Override + public void init(AnyValue conf) { + super.init(conf); + if (conf == null) { + conf = AnyValue.create(); + } + initClient(conf); + } + + private void initClient(AnyValue conf) { + String password = null; + int urlmaxconns = Utility.cpus(); + int urlpipelines = org.redkale.net.client.Client.DEFAULT_MAX_PIPELINES; + for (AnyValue node : getNodes(conf)) { + String urluser = ""; + String urlpwd = ""; + String urldb = ""; + String addrstr = node.getValue(CACHE_SOURCE_URL, node.getValue("addr")); //兼容addr + if (addrstr.startsWith("redis://")) { //兼容 redis://:1234@127.0.0.1:6379?db=2 + URI uri = URI.create(addrstr); + address = new InetSocketAddress(uri.getHost(), uri.getPort() > 0 ? uri.getPort() : 6379); + String userInfo = uri.getUserInfo(); + if (userInfo == null || userInfo.isEmpty()) { + String authority = uri.getAuthority(); + if (authority != null && authority.indexOf('@') > 0) { + userInfo = authority.substring(0, authority.indexOf('@')); + } + } + if (userInfo != null && !userInfo.isEmpty()) { + urlpwd = userInfo; + if (urlpwd.startsWith(":")) { + urlpwd = urlpwd.substring(1); + } else { + int index = urlpwd.indexOf(':'); + if (index > 0) { + urluser = urlpwd.substring(0, index); + urlpwd = urlpwd.substring(index + 1); + } + } + } + if (uri.getQuery() != null && !uri.getQuery().isEmpty()) { + String[] qrys = uri.getQuery().split("&|="); + for (int i = 0; i < qrys.length; i += 2) { + if (CACHE_SOURCE_USER.equals(qrys[i])) { + urluser = i == qrys.length - 1 ? "" : qrys[i + 1]; + } else if (CACHE_SOURCE_PASSWORD.equals(qrys[i])) { + urlpwd = i == qrys.length - 1 ? "" : qrys[i + 1]; + } else if (CACHE_SOURCE_DB.equals(qrys[i])) { + urldb = i == qrys.length - 1 ? "" : qrys[i + 1]; + } else if (CACHE_SOURCE_MAXCONNS.equals(qrys[i])) { + urlmaxconns = i == qrys.length - 1 ? Utility.cpus() : Integer.parseInt(qrys[i + 1]); + } else if (CACHE_SOURCE_PIPELINES.equals(qrys[i])) { + urlpipelines = i == qrys.length - 1 ? org.redkale.net.client.Client.DEFAULT_MAX_PIPELINES : Integer.parseInt(qrys[i + 1]); + } + } + } + } else { //兼容addr和port分开 + address = new InetSocketAddress(addrstr, node.getIntValue("port")); + } + password = node.getValue(CACHE_SOURCE_PASSWORD, urlpwd).trim(); + String db0 = node.getValue(CACHE_SOURCE_DB, urldb).trim(); + if (!db0.isEmpty()) { + db = Integer.valueOf(db0); + } + break; + } + AsyncGroup ioGroup = clientAsyncGroup; + if (clientAsyncGroup == null) { + String f = "Redkalex-Redis-IOThread-" + resourceName() + "-%s"; + ioGroup = AsyncGroup.create(f, workExecutor, 16 * 1024, Utility.cpus() * 4).start(); + } + int maxconns = conf.getIntValue(CACHE_SOURCE_MAXCONNS, urlmaxconns); + int pipelines = conf.getIntValue(CACHE_SOURCE_PIPELINES, urlpipelines); + RedisCacheClient old = this.client; + + if (passwordDecoder != null) { + password = passwordDecoder.apply(password); + } + this.client = new RedisCacheClient(resourceName(), ioGroup, resourceName() + "." + db, new ClientAddress(address), maxconns, pipelines, + password == null || password.isEmpty() ? null : new RedisCacheReqAuth(password), db > 0 ? new RedisCacheReqDB(db) : null); + if (old != null) { + old.close(); + } + //if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, RedisCacheSource.class.getSimpleName() + ": addr=" + address + ", db=" + db); + } + + @Override + @ResourceListener + public void onResourceChange(ResourceEvent[] events) { + if (events == null || events.length < 1) { + return; + } + StringBuilder sb = new StringBuilder(); + for (ResourceEvent event : events) { + sb.append("CacheSource(name=").append(resourceName()).append(") change '").append(event.name()).append("' to '").append(event.coverNewValue()).append("'\r\n"); + } + initClient(this.config); + if (sb.length() > 0) { + logger.log(Level.INFO, sb.toString()); + } + } + + public boolean acceptsConf(AnyValue config) { + if (config == null) { + return false; + } + AnyValue[] nodes = getNodes(config); + if (nodes == null || nodes.length == 0) { + return false; + } + for (AnyValue node : nodes) { + String val = node.getValue(CACHE_SOURCE_URL, node.getValue("addr")); //兼容addr + if (val != null && val.startsWith("redis://")) { + return true; + } + } + return false; + } + + protected AnyValue[] getNodes(AnyValue config) { + AnyValue[] nodes = config.getAnyValues(CACHE_SOURCE_NODE); + if (nodes == null || nodes.length == 0) { + AnyValue one = config.getAnyValue(CACHE_SOURCE_NODE); + if (one == null) { + String val = config.getValue(CACHE_SOURCE_URL); + if (val == null) { + return nodes; + } + nodes = new AnyValue[]{config}; + } else { + nodes = new AnyValue[]{one}; + } + } + return nodes; + } + + @Override + public final String getType() { + return "redis"; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "{name=" + resourceName() + ", addrs=" + this.address + ", db=" + this.db + "}"; + } + + @Override + public void destroy(AnyValue conf) { + super.destroy(conf); + if (client != null) { + client.close(); + } + } + + //--------------------- exists ------------------------------ + @Override + public CompletableFuture existsAsync(String key) { + return sendAsync("EXISTS", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getIntValue(0) > 0); + } + + @Override + public boolean exists(String key) { + return existsAsync(key).join(); + } + + //--------------------- get ------------------------------ + @Override + public CompletableFuture getAsync(String key, Type type) { + return sendAsync("GET", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getObjectValue(key, cryptor, type)); + } + + @Override + public CompletableFuture getStringAsync(String key) { + return sendAsync("GET", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getStringValue(key, cryptor)); + } + + @Override + public CompletableFuture getSetStringAsync(String key, String value) { + return sendAsync("GETSET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getStringValue(key, cryptor)); + } + + @Override + public CompletableFuture getLongAsync(String key, long defValue) { + return sendAsync("GET", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getLongValue(defValue)); + } + + @Override + public CompletableFuture getSetLongAsync(String key, long value, long defValue) { + return sendAsync("GETSET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(value)).thenApply(v -> v.getLongValue(defValue)); + } + + @Override + public T get(String key, final Type type) { + return (T) getAsync(key, type).join(); + } + + @Override + public String getString(String key) { + return getStringAsync(key).join(); + } + + @Override + public String getSetString(String key, String value) { + return getSetStringAsync(key, value).join(); + } + + @Override + public long getLong(String key, long defValue) { + return getLongAsync(key, defValue).join(); + } + + @Override + public long getSetLong(String key, long value, long defValue) { + return getSetLongAsync(key, value, defValue).join(); + } + + //--------------------- getex ------------------------------ + @Override + public CompletableFuture getexAsync(String key, int expireSeconds, final Type type) { + return sendAsync("GETEX", key, key.getBytes(StandardCharsets.UTF_8), "EX".getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getObjectValue(key, cryptor, type)); + } + + @Override + public T getex(String key, final int expireSeconds, final Type type) { + return (T) getexAsync(key, expireSeconds, type).join(); + } + + @Override + public CompletableFuture getexStringAsync(String key, int expireSeconds) { + return sendAsync("GETEX", key, key.getBytes(StandardCharsets.UTF_8), "EX".getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getStringValue(key, cryptor)); + } + + @Override + public String getexString(String key, final int expireSeconds) { + return getexStringAsync(key, expireSeconds).join(); + } + + @Override + public CompletableFuture getexLongAsync(String key, int expireSeconds, long defValue) { + return sendAsync("GETEX", key, key.getBytes(StandardCharsets.UTF_8), "EX".getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getLongValue(defValue)); + } + + @Override + public long getexLong(String key, final int expireSeconds, long defValue) { + return getexLongAsync(key, expireSeconds, defValue).join(); + } + + @Override + public CompletableFuture getexBytesAsync(final String key, final int expireSeconds) { + return sendAsync("GETEX", key, key.getBytes(StandardCharsets.UTF_8), "EX".getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getFrameValue()); + } + + @Override + public byte[] getexBytes(final String key, final int expireSeconds) { + return getexBytesAsync(key, expireSeconds).join(); + } + + @Override + public CompletableFuture msetAsync(final Object... keyVals) { + if (keyVals.length % 2 != 0) { + throw new RedkaleException("key value must be paired"); + } + byte[][] bs = new byte[keyVals.length][]; + for (int i = 0; i < keyVals.length; i += 2) { + String key = keyVals[i].toString(); + bs[i] = key.getBytes(StandardCharsets.UTF_8); + bs[i + 1] = formatValue(key, cryptor, keyVals[i + 1]); + } + return sendAsync("MSET", keyVals[0].toString(), bs).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture msetAsync(final Map map) { + if (map == null || map.isEmpty()) { + return CompletableFuture.completedFuture(null); + } + List bs = new ArrayList<>(); + StringWrapper onekey = new StringWrapper(); + map.forEach((key, val) -> { + onekey.setValue(key.toString()); + bs.add(key.toString().getBytes(StandardCharsets.UTF_8)); + bs.add(formatValue(key.toString(), cryptor, val)); + }); + return sendAsync("MSET", onekey.getValue(), bs.toArray(new byte[bs.size()][])).thenApply(v -> v.getVoidValue()); + } + + //--------------------- setex ------------------------------ + @Override + public CompletableFuture setAsync(String key, final Type type, T value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, (Convert) null, type, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture setAsync(String key, Convert convert, final Type type, T value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, convert, type, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture setnxAsync(String key, final Type type, T value) { + return sendAsync("SETNX", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, (Convert) null, type, value)).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture setnxAsync(String key, Convert convert, final Type type, T value) { + return sendAsync("SETNX", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, convert, type, value)).thenApply(v -> v.getBoolValue()); + } + + @Override + public boolean setnxBytes(final String key, final byte[] value) { + return setnxBytesAsync(key, value).join(); + } + + @Override + public CompletableFuture setnxBytesAsync(final String key, byte[] value) { + return sendAsync("SETNX", key, key.getBytes(StandardCharsets.UTF_8), value).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture getSetAsync(String key, final Type type, T value) { + return sendAsync("GETSET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, (Convert) null, type, value)).thenApply(v -> v.getObjectValue(key, cryptor, type)); + } + + @Override + public CompletableFuture getSetAsync(String key, Convert convert, final Type type, T value) { + return sendAsync("GETSET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, convert, type, value)).thenApply(v -> v.getObjectValue(key, cryptor, type)); + } + + @Override + public void mset(final Object... keyVals) { + msetAsync(keyVals).join(); + } + + @Override + public void mset(final Map map) { + msetAsync(map).join(); + } + + @Override + public void set(final String key, final Type type, T value) { + setAsync(key, type, value).join(); + } + + @Override + public void set(String key, final Convert convert, final Type type, T value) { + setAsync(key, convert, type, value).join(); + } + + @Override + public boolean setnx(final String key, final Type type, T value) { + return setnxAsync(key, type, value).join(); + } + + @Override + public boolean setnx(String key, final Convert convert, final Type type, T value) { + return setnxAsync(key, convert, type, value).join(); + } + + @Override + public T getSet(String key, final Type type, T value) { + return getSetAsync(key, type, value).join(); + } + + @Override + public T getSet(String key, Convert convert, final Type type, T value) { + return getSetAsync(key, convert, type, value).join(); + } + + @Override + public CompletableFuture setStringAsync(String key, String value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture setnxStringAsync(String key, String value) { + return sendAsync("SETNX", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getBoolValue()); + } + + @Override + public void setString(String key, String value) { + setStringAsync(key, value).join(); + } + + @Override + public boolean setnxString(String key, String value) { + return setnxStringAsync(key, value).join(); + } + + @Override + public CompletableFuture setLongAsync(String key, long value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture setnxLongAsync(String key, long value) { + return sendAsync("SETNX", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getBoolValue()); + } + + @Override + public void setLong(String key, long value) { + setLongAsync(key, value).join(); + } + + @Override + public boolean setnxLong(String key, long value) { + return setnxLongAsync(key, value).join(); + } + + //--------------------- setex ------------------------------ + @Override + public CompletableFuture setexAsync(String key, int expireSeconds, final Type type, T value) { + return sendAsync("SETEX", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, (Convert) null, type, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture setexAsync(String key, int expireSeconds, Convert convert, final Type type, T value) { + return sendAsync("SETEX", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, convert, type, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public void setex(String key, int expireSeconds, final Type type, T value) { + setexAsync(key, expireSeconds, type, value).join(); + } + + @Override + public void setex(String key, int expireSeconds, Convert convert, final Type type, T value) { + setexAsync(key, expireSeconds, convert, type, value).join(); + } + + @Override + public CompletableFuture setexStringAsync(String key, int expireSeconds, String value) { + return sendAsync("SETEX", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public void setexString(String key, int expireSeconds, String value) { + setexStringAsync(key, expireSeconds, value).join(); + } + + @Override + public CompletableFuture setexLongAsync(String key, int expireSeconds, long value) { + return sendAsync("SETEX", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public void setexLong(String key, int expireSeconds, long value) { + setexLongAsync(key, expireSeconds, value).join(); + } + + @Override + public CompletableFuture setnxexStringAsync(String key, int expireSeconds, String value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value), NX, EX, String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture setnxexLongAsync(String key, int expireSeconds, long value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value), NX, EX, String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture setnxexBytesAsync(String key, int expireSeconds, byte[] value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), value, NX, EX, String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture setnxexAsync(String key, int expireSeconds, final Type type, T value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, (Convert) null, type, value), NX, EX, String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture setnxexAsync(String key, int expireSeconds, Convert convert, final Type type, T value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, convert, type, value), NX, EX, String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getBoolValue()); + } + + @Override + public boolean setnxex(final String key, final int expireSeconds, final Type type, final T value) { + return setnxexAsync(key, expireSeconds, type, value).join(); + } + + @Override + public boolean setnxex(final String key, final int expireSeconds, final Convert convert, final Type type, final T value) { + return setnxexAsync(key, expireSeconds, convert, type, value).join(); + } + + @Override + public boolean setnxexString(final String key, final int expireSeconds, final String value) { + return setnxexStringAsync(key, expireSeconds, value).join(); + } + + @Override + public boolean setnxexLong(final String key, final int expireSeconds, final long value) { + return setnxexLongAsync(key, expireSeconds, value).join(); + } + + @Override + public boolean setnxexBytes(final String key, final int expireSeconds, final byte[] value) { + return setnxexBytesAsync(key, expireSeconds, value).join(); + } + + //--------------------- expire ------------------------------ + @Override + public CompletableFuture expireAsync(String key, int expireSeconds) { + return sendAsync("EXPIRE", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getVoidValue()); + } + + @Override + public void expire(String key, int expireSeconds) { + expireAsync(key, expireSeconds).join(); + } + + //--------------------- del ------------------------------ + @Override + public CompletableFuture delAsync(String... keys) { + if (keys.length == 0) { + return CompletableFuture.completedFuture(0); + } + if (keys.length == 1) { + return sendAsync("DEL", keys[0], keys[0].getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getIntValue(0)); + } else { + byte[][] bs = new byte[keys.length][]; + for (int i = 0; i < keys.length; i++) { + bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); + } + return sendAsync("DEL", keys[0], bs).thenApply(v -> v.getIntValue(0)); + } + } + + @Override + public int del(String... keys) { + return delAsync(keys).join(); + } + + //--------------------- incrby ------------------------------ + @Override + public long incr(final String key) { + return incrAsync(key).join(); + } + + @Override + public CompletableFuture incrAsync(final String key) { + return sendAsync("INCR", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getLongValue(0L)); + } + + @Override + public long incrby(final String key, long num) { + return incrbyAsync(key, num).join(); + } + + @Override + public double incrbyFloat(final String key, double num) { + return incrbyFloatAsync(key, num).join(); + } + + @Override + public CompletableFuture incrbyAsync(final String key, long num) { + return sendAsync("INCRBY", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getLongValue(0L)); + } + + @Override + public CompletableFuture incrbyFloatAsync(final String key, double num) { + return sendAsync("INCRBYFLOAT", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getDoubleValue(0.d)); + } + + //--------------------- decrby ------------------------------ + @Override + public long decr(final String key) { + return decrAsync(key).join(); + } + + @Override + public CompletableFuture decrAsync(final String key) { + return sendAsync("DECR", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getLongValue(0L)); + } + + @Override + public long decrby(final String key, long num) { + return decrbyAsync(key, num).join(); + } + + @Override + public CompletableFuture decrbyAsync(final String key, long num) { + return sendAsync("DECRBY", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getLongValue(0L)); + } + + @Override + public int hdel(final String key, String... fields) { + return hdelAsync(key, fields).join(); + } + + @Override + public int hlen(final String key) { + return hlenAsync(key).join(); + } + + @Override + public List hkeys(final String key) { + return hkeysAsync(key).join(); + } + + @Override + public long hincr(final String key, String field) { + return hincrAsync(key, field).join(); + } + + @Override + public long hincrby(final String key, String field, long num) { + return hincrbyAsync(key, field, num).join(); + } + + @Override + public double hincrbyFloat(final String key, String field, double num) { + return hincrbyFloatAsync(key, field, num).join(); + } + + @Override + public long hdecr(final String key, String field) { + return hdecrAsync(key, field).join(); + } + + @Override + public long hdecrby(final String key, String field, long num) { + return hdecrbyAsync(key, field, num).join(); + } + + @Override + public boolean hexists(final String key, String field) { + return hexistsAsync(key, field).join(); + } + + @Override + public void hset(final String key, final String field, final Type type, final T value) { + hsetAsync(key, field, type, value).join(); + } + + @Override + public void hset(final String key, final String field, final Convert convert, final Type type, final T value) { + hsetAsync(key, field, convert, type, value).join(); + } + + @Override + public void hsetString(final String key, final String field, final String value) { + hsetStringAsync(key, field, value).join(); + } + + @Override + public void hsetLong(final String key, final String field, final long value) { + hsetLongAsync(key, field, value).join(); + } + + @Override + public boolean hsetnx(final String key, final String field, final Type type, final T value) { + return hsetnxAsync(key, field, type, value).join(); + } + + @Override + public boolean hsetnx(final String key, final String field, final Convert convert, final Type type, final T value) { + return hsetnxAsync(key, field, convert, type, value).join(); + } + + @Override + public boolean hsetnxString(final String key, final String field, final String value) { + return hsetnxStringAsync(key, field, value).join(); + } + + @Override + public boolean hsetnxLong(final String key, final String field, final long value) { + return hsetnxLongAsync(key, field, value).join(); + } + + @Override + public void hmset(final String key, final Serializable... values) { + hmsetAsync(key, values).join(); + } + + @Override + public void hmset(final String key, final Map map) { + hmsetAsync(key, map).join(); + } + + @Override + public List hmget(final String key, final Type type, final String... fields) { + return hmgetAsync(key, type, fields).join(); + } + + @Override + public Map hmap(final String key, final Type type, int offset, int limit, String pattern) { + return (Map) hmapAsync(key, type, offset, limit, pattern).join(); + } + + @Override + public Map hmap(final String key, final Type type, int offset, int limit) { + return (Map) hmapAsync(key, type, offset, limit).join(); + } + + @Override + public T hget(final String key, final String field, final Type type) { + return (T) hgetAsync(key, field, type).join(); + } + + @Override + public String hgetString(final String key, final String field) { + return hgetStringAsync(key, field).join(); + } + + @Override + public long hgetLong(final String key, final String field, long defValue) { + return hgetLongAsync(key, field, defValue).join(); + } + + @Override + public CompletableFuture hdelAsync(final String key, String... fields) { + byte[][] bs = new byte[fields.length + 1][]; + bs[0] = key.getBytes(StandardCharsets.UTF_8); + for (int i = 0; i < fields.length; i++) { + bs[i + 1] = fields[i].getBytes(StandardCharsets.UTF_8); + } + return sendAsync("HDEL", key, bs).thenApply(v -> v.getIntValue(0)); + } + + @Override + public CompletableFuture hlenAsync(final String key) { + return sendAsync("HLEN", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getIntValue(0)); + } + + @Override + public CompletableFuture> hkeysAsync(final String key) { + return sendAsync("HKEYS", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> (List) v.getListValue(key, cryptor, String.class)); + } + + @Override + public CompletableFuture hincrAsync(final String key, String field) { + return hincrbyAsync(key, field, 1); + } + + @Override + public CompletableFuture hincrbyAsync(final String key, String field, long num) { + return sendAsync("HINCRBY", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getLongValue(0L)); + } + + @Override + public CompletableFuture hincrbyFloatAsync(final String key, String field, double num) { + return sendAsync("HINCRBYFLOAT", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), String.valueOf(num).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getDoubleValue(0.d)); + } + + @Override + public CompletableFuture hdecrAsync(final String key, String field) { + return hincrbyAsync(key, field, -1); + } + + @Override + public CompletableFuture hdecrbyAsync(final String key, String field, long num) { + return hincrbyAsync(key, field, -num); + } + + @Override + public CompletableFuture hexistsAsync(final String key, String field) { + return sendAsync("HEXISTS", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getIntValue(0) > 0); + } + + @Override + public CompletableFuture hsetAsync(final String key, final String field, final Type type, final T value) { + if (value == null) { + return CompletableFuture.completedFuture(null); + } + return sendAsync("HSET", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, null, type, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture hsetAsync(final String key, final String field, final Convert convert, final Type type, final T value) { + if (value == null) { + return CompletableFuture.completedFuture(null); + } + return sendAsync("HSET", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, convert, type, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture hsetStringAsync(final String key, final String field, final String value) { + if (value == null) { + return CompletableFuture.completedFuture(null); + } + return sendAsync("HSET", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture hsetLongAsync(final String key, final String field, final long value) { + return sendAsync("HSET", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture hsetnxAsync(final String key, final String field, final Type type, final T value) { + if (value == null) { + return CompletableFuture.completedFuture(null); + } + return sendAsync("HSETNX", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, null, type, value)).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture hsetnxAsync(final String key, final String field, final Convert convert, final Type type, final T value) { + if (value == null) { + return CompletableFuture.completedFuture(null); + } + return sendAsync("HSETNX", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, convert, type, value)).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture hsetnxStringAsync(final String key, final String field, final String value) { + if (value == null) { + return CompletableFuture.completedFuture(false); + } + return sendAsync("HSETNX", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture hsetnxLongAsync(final String key, final String field, final long value) { + return sendAsync("HSETNX", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getBoolValue()); + } + + @Override + public CompletableFuture hmsetAsync(final String key, final Serializable... values) { + byte[][] bs = new byte[values.length + 1][]; + bs[0] = key.getBytes(StandardCharsets.UTF_8); + for (int i = 0; i < values.length; i += 2) { + bs[i + 1] = String.valueOf(values[i]).getBytes(StandardCharsets.UTF_8); + bs[i + 2] = formatValue(key, cryptor, values[i + 1]); + } + return sendAsync("HMSET", key, bs).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture hmsetAsync(final String key, final Map map) { + if (map == null || map.isEmpty()) { + return CompletableFuture.completedFuture(null); + } + List bs = new ArrayList<>(); + bs.add(key.getBytes(StandardCharsets.UTF_8)); + map.forEach((k, v) -> { + bs.add(k.toString().getBytes(StandardCharsets.UTF_8)); + bs.add(formatValue(k.toString(), cryptor, v)); + }); + return sendAsync("HMSET", key, bs.toArray(new byte[bs.size()][])).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture> hmgetAsync(final String key, final Type type, final String... fields) { + byte[][] bs = new byte[fields.length + 1][]; + bs[0] = key.getBytes(StandardCharsets.UTF_8); + for (int i = 0; i < fields.length; i++) { + bs[i + 1] = fields[i].getBytes(StandardCharsets.UTF_8); + } + return sendAsync("HMGET", key, bs).thenApply(v -> (List) v.getListValue(key, cryptor, type)); + } + + @Override + public CompletableFuture> hmapAsync(final String key, final Type type, int offset, int limit) { + return hmapAsync(key, type, offset, limit, null); + } + + @Override + public CompletableFuture> hmapAsync(final String key, final Type type, int offset, int limit, String pattern) { + byte[][] bs = new byte[pattern == null || pattern.isEmpty() ? 4 : 6][limit]; + int index = -1; + bs[++index] = key.getBytes(StandardCharsets.UTF_8); + bs[++index] = String.valueOf(offset).getBytes(StandardCharsets.UTF_8); + if (pattern != null && !pattern.isEmpty()) { + bs[++index] = "MATCH".getBytes(StandardCharsets.UTF_8); + bs[++index] = pattern.getBytes(StandardCharsets.UTF_8); + } + bs[++index] = "COUNT".getBytes(StandardCharsets.UTF_8); + bs[++index] = String.valueOf(limit).getBytes(StandardCharsets.UTF_8); + return sendAsync("HSCAN", key, bs).thenApply(v -> v.getMapValue(key, cryptor, type)); + } + + @Override + public CompletableFuture hgetAsync(final String key, final String field, final Type type) { + return sendAsync("HGET", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getObjectValue(key, cryptor, type)); + } + + @Override + public CompletableFuture hgetStringAsync(final String key, final String field) { + return sendAsync("HGET", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getStringValue(key, cryptor)); + } + + @Override + public CompletableFuture hgetLongAsync(final String key, final String field, long defValue) { + return sendAsync("HGET", key, key.getBytes(StandardCharsets.UTF_8), field.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getLongValue(defValue)); + } + + @Override + public CompletableFuture> smembersAsync(String key, final Type componentType) { + return sendAsync("SMEMBERS", key, keySetArgs(key)).thenApply(v -> v.getSetValue(key, cryptor, componentType)); + } + + @Override + public CompletableFuture> lrangeAsync(String key, final Type componentType) { + return sendAsync("LRANGE", key, keyListArgs(key)).thenApply(v -> v.getListValue(key, cryptor, componentType)); + } + + //--------------------- collection ------------------------------ + @Override + public CompletableFuture llenAsync(String key) { + return sendAsync("LLEN", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getIntValue(0)); + } + + @Override + public CompletableFuture scardAsync(String key) { + return sendAsync("SCARD", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getIntValue(0)); + } + + @Override + public int llen(String key) { + return llenAsync(key).join(); + } + + @Override + public int scard(String key) { + return scardAsync(key).join(); + } + + @Override + public CompletableFuture> mgetLongAsync(String... keys) { + byte[][] bs = new byte[keys.length][]; + for (int i = 0; i < bs.length; i++) { + bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); + } + return sendAsync("MGET", keys[0], bs).thenApply(v -> { + List list = (List) v.getListValue(keys[0], cryptor, long.class); + Map map = new LinkedHashMap<>(); + for (int i = 0; i < keys.length; i++) { + Object obj = list.get(i); + if (obj != null) { + map.put(keys[i], list.get(i)); + } + } + return map; + }); + } + + @Override + public CompletableFuture> mgetStringAsync(final String... keys) { + byte[][] bs = new byte[keys.length][]; + for (int i = 0; i < bs.length; i++) { + bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); + } + return sendAsync("MGET", keys[0], bs).thenApply(v -> { + List list = (List) v.getListValue(keys[0], cryptor, String.class); + Map map = new LinkedHashMap<>(); + for (int i = 0; i < keys.length; i++) { + Object obj = list.get(i); + if (obj != null) { + map.put(keys[i], list.get(i)); + } + } + return map; + }); + } + + @Override + public CompletableFuture> mgetAsync(final Type componentType, final String... keys) { + byte[][] bs = new byte[keys.length][]; + for (int i = 0; i < bs.length; i++) { + bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); + } + return sendAsync("MGET", keys[0], bs).thenApply(v -> { + List list = (List) v.getListValue(keys[0], cryptor, componentType); + Map map = new LinkedHashMap<>(); + for (int i = 0; i < keys.length; i++) { + Object obj = list.get(i); + if (obj != null) { + map.put(keys[i], list.get(i)); + } + } + return map; + }); + } + + @Override + public CompletableFuture> mgetBytesAsync(final String... keys) { + byte[][] bs = new byte[keys.length][]; + for (int i = 0; i < bs.length; i++) { + bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); + } + return sendAsync("MGET", keys[0], bs).thenApply(v -> { + List list = (List) v.getListValue(keys[0], cryptor, byte[].class); + Map map = new LinkedHashMap<>(); + for (int i = 0; i < keys.length; i++) { + Object obj = list.get(i); + if (obj != null) { + map.put(keys[i], list.get(i)); + } + } + return map; + }); + } + + @Override + public CompletableFuture>> smembersAsync(final Type componentType, final String... keys) { + final CompletableFuture>> rsFuture = new CompletableFuture<>(); + final Map> map = new LinkedHashMap<>(); + final ReentrantLock mapLock = new ReentrantLock(); + final CompletableFuture[] futures = new CompletableFuture[keys.length]; + for (int i = 0; i < keys.length; i++) { + final String key = keys[i]; + futures[i] = sendAsync("SMEMBERS", key, keySetArgs(key)).thenAccept(v -> { + Set c = v.getSetValue(key, cryptor, componentType); + if (c != null) { + mapLock.lock(); + try { + map.put(key, c); + } finally { + mapLock.unlock(); + } + } + }); + } + CompletableFuture.allOf(futures).whenComplete((w, e) -> { + if (e != null) { + rsFuture.completeExceptionally(e); + } else { + rsFuture.complete(map); + } + }); + return rsFuture; + } + + @Override + public CompletableFuture>> lrangeAsync(final Type componentType, final String... keys) { + final CompletableFuture>> rsFuture = new CompletableFuture<>(); + final Map> map = new LinkedHashMap<>(); + final ReentrantLock mapLock = new ReentrantLock(); + final CompletableFuture[] futures = new CompletableFuture[keys.length]; + for (int i = 0; i < keys.length; i++) { + final String key = keys[i]; + futures[i] = sendAsync("LRANGE", key, keyListArgs(key)).thenAccept(v -> { + List c = v.getListValue(key, cryptor, componentType); + if (c != null) { + mapLock.lock(); + try { + map.put(key, c); + } finally { + mapLock.unlock(); + } + } + }); + } + CompletableFuture.allOf(futures).whenComplete((w, e) -> { + if (e != null) { + rsFuture.completeExceptionally(e); + } else { + rsFuture.complete(map); + } + }); + return rsFuture; + } + + @Override + public Set smembers(String key, final Type componentType) { + return (Set) smembersAsync(key, componentType).join(); + } + + @Override + public List lrange(String key, final Type componentType) { + return (List) lrangeAsync(key, componentType).join(); + } + + @Override + public Map mgetBytes(final String... keys) { + return mgetBytesAsync(keys).join(); + } + + @Override + public Map mgetLong(final String... keys) { + return mgetLongAsync(keys).join(); + } + + @Override + public Map mgetString(final String... keys) { + return mgetStringAsync(keys).join(); + } + + @Override + public Map mget(final Type componentType, final String... keys) { + return (Map) mgetAsync(componentType, keys).join(); + } + + @Override + public Map> smembers(final Type componentType, String... keys) { + return (Map) smembersAsync(componentType, keys).join(); + } + + @Override + public Map> lrange(final Type componentType, String... keys) { + return (Map) lrangeAsync(componentType, keys).join(); + } + + //--------------------- existsItem ------------------------------ + @Override + public boolean sismember(String key, final Type componentType, T value) { + return sismemberAsync(key, componentType, value).join(); + } + + @Override + public CompletableFuture sismemberAsync(String key, final Type componentType, T value) { + return sendAsync("SISMEMBER", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, (Convert) null, componentType, value)).thenApply(v -> v.getIntValue(0) > 0); + } + + @Override + public boolean sismemberString(String key, String value) { + return sismemberStringAsync(key, value).join(); + } + + @Override + public CompletableFuture sismemberStringAsync(String key, String value) { + return sendAsync("SISMEMBER", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getIntValue(0) > 0); + } + + @Override + public boolean sismemberLong(String key, long value) { + return sismemberLongAsync(key, value).join(); + } + + @Override + public CompletableFuture sismemberLongAsync(String key, long value) { + return sendAsync("SISMEMBER", key, key.getBytes(StandardCharsets.UTF_8), formatValue(value)).thenApply(v -> v.getIntValue(0) > 0); + } + + //--------------------- rpush ------------------------------ + @Override + public CompletableFuture rpushAsync(String key, final Type componentType, T value) { + return sendAsync("RPUSH", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, (Convert) null, componentType, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public void rpush(String key, final Type componentType, T value) { + rpushAsync(key, componentType, value).join(); + } + + @Override + public CompletableFuture rpushStringAsync(String key, String value) { + return sendAsync("RPUSH", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public void rpushString(String key, String value) { + rpushStringAsync(key, value).join(); + } + + @Override + public CompletableFuture rpushLongAsync(String key, long value) { + return sendAsync("RPUSH", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public void rpushLong(String key, long value) { + rpushLongAsync(key, value).join(); + } + + //--------------------- lrem ------------------------------ + @Override + public CompletableFuture lremAsync(String key, final Type componentType, T value) { + return sendAsync("LREM", key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(key, cryptor, (Convert) null, componentType, value)).thenApply(v -> v.getIntValue(0)); + } + + @Override + public int lrem(String key, final Type componentType, T value) { + return lremAsync(key, componentType, value).join(); + } + + @Override + public CompletableFuture lremStringAsync(String key, String value) { + return sendAsync("LREM", key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(key, cryptor, value)).thenApply(v -> v.getIntValue(0)); + } + + @Override + public int lremString(String key, String value) { + return lremStringAsync(key, value).join(); + } + + @Override + public CompletableFuture lremLongAsync(String key, long value) { + return sendAsync("LREM", key, key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, formatValue(key, cryptor, value)).thenApply(v -> v.getIntValue(0)); + } + + @Override + public int lremLong(String key, long value) { + return lremLongAsync(key, value).join(); + } + + //--------------------- sadd ------------------------------ + @Override + public CompletableFuture saddAsync(String key, Type componentType, T value) { + return sendAsync("SADD", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, (Convert) null, componentType, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture spopAsync(String key, Type componentType) { + return sendAsync("SPOP", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getObjectValue(key, cryptor, componentType)); + } + + @Override + public CompletableFuture> spopAsync(String key, int count, Type componentType) { + return sendAsync("SPOP", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getObjectValue(key, cryptor, componentType)); + } + + @Override + public CompletableFuture spopStringAsync(String key) { + return sendAsync("SPOP", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getStringValue(key, cryptor)); + } + + @Override + public CompletableFuture> spopStringAsync(String key, int count) { + return sendAsync("SPOP", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8)).thenApply(v -> (Set) v.getSetValue(key, cryptor, String.class)); + } + + @Override + public CompletableFuture spopLongAsync(String key) { + return sendAsync("SPOP", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getLongValue(0L)); + } + + @Override + public CompletableFuture> spopLongAsync(String key, int count) { + return sendAsync("SPOP", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(count).getBytes(StandardCharsets.UTF_8)).thenApply(v -> (Set) v.getSetValue(key, cryptor, long.class)); + } + + @Override + public void sadd(String key, final Type componentType, T value) { + saddAsync(key, componentType, value).join(); + } + + @Override + public T spop(String key, final Type componentType) { + return (T) spopAsync(key, componentType).join(); + } + + @Override + public Set spop(String key, int count, final Type componentType) { + return (Set) spopAsync(key, count, componentType).join(); + } + + @Override + public String spopString(String key) { + return spopStringAsync(key).join(); + } + + @Override + public Set spopString(String key, int count) { + return spopStringAsync(key, count).join(); + } + + @Override + public Long spopLong(String key) { + return spopLongAsync(key).join(); + } + + @Override + public Set spopLong(String key, int count) { + return spopLongAsync(key, count).join(); + } + + @Override + public CompletableFuture saddStringAsync(String key, String value) { + return sendAsync("SADD", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public void saddString(String key, String value) { + saddStringAsync(key, value).join(); + } + + @Override + public CompletableFuture saddLongAsync(String key, long value) { + return sendAsync("SADD", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getVoidValue()); + } + + @Override + public void saddLong(String key, long value) { + saddLongAsync(key, value).join(); + } + + //--------------------- srem ------------------------------ + @Override + public CompletableFuture sremAsync(String key, final Type componentType, T value) { + return sendAsync("SREM", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, (Convert) null, componentType, value)).thenApply(v -> v.getIntValue(0)); + } + + @Override + public int srem(String key, final Type componentType, T value) { + return sremAsync(key, componentType, value).join(); + } + + @Override + public CompletableFuture sremStringAsync(String key, String value) { + return sendAsync("SREM", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getIntValue(0)); + } + + @Override + public int sremString(String key, String value) { + return sremStringAsync(key, value).join(); + } + + @Override + public CompletableFuture sremLongAsync(String key, long value) { + return sendAsync("SREM", key, key.getBytes(StandardCharsets.UTF_8), formatValue(key, cryptor, value)).thenApply(v -> v.getIntValue(0)); + } + + @Override + public int sremLong(String key, long value) { + return sremLongAsync(key, value).join(); + } + + //--------------------- keys ------------------------------ + @Override + public List keys(String pattern) { + return keysAsync(pattern).join(); + } + + @Override + public byte[] getBytes(final String key) { + return getBytesAsync(key).join(); + } + + @Override + public byte[] getSetBytes(final String key, final byte[] value) { + return getSetBytesAsync(key, value).join(); + } + + @Override + public void setBytes(final String key, final byte[] value) { + setBytesAsync(key, value).join(); + } + + @Override + public void setexBytes(final String key, final int expireSeconds, final byte[] value) { + setexBytesAsync(key, expireSeconds, value).join(); + } + + @Override + public CompletableFuture getBytesAsync(final String key) { + return sendAsync("GET", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getFrameValue()); + } + + @Override + public CompletableFuture getSetBytesAsync(final String key, final byte[] value) { + return sendAsync("GETSET", key, key.getBytes(StandardCharsets.UTF_8), value).thenApply(v -> v.getFrameValue()); + } + + @Override + public CompletableFuture setBytesAsync(final String key, final byte[] value) { + return sendAsync("SET", key, key.getBytes(StandardCharsets.UTF_8), value).thenApply(v -> v.getVoidValue()); + + } + + @Override + public CompletableFuture setexBytesAsync(final String key, final int expireSeconds, final byte[] value) { + return sendAsync("SETEX", key, key.getBytes(StandardCharsets.UTF_8), String.valueOf(expireSeconds).getBytes(StandardCharsets.UTF_8), value).thenApply(v -> v.getVoidValue()); + } + + @Override + public CompletableFuture> keysAsync(String pattern) { + String key = pattern == null || pattern.isEmpty() ? "*" : pattern; + return sendAsync("KEYS", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> (List) v.getListValue(key, cryptor, String.class)); + } + + //--------------------- dbsize ------------------------------ + @Override + public long dbsize() { + return dbsizeAsync().join(); + } + + @Override + public CompletableFuture dbsizeAsync() { + return sendAsync("DBSIZE", null).thenApply(v -> v.getLongValue(0L)); + } + + //--------------------- send ------------------------------ + @Local + public CompletableFuture sendAsync(final String command, final String key, final Serializable... args) { + int start = key == null ? 0 : 1; + byte[][] bs = new byte[args.length + start][]; + if (key != null) { + bs[0] = key.getBytes(StandardCharsets.UTF_8); + for (int i = start; i < bs.length; i++) { + if (args[i - start].getClass() == String.class) { + bs[i] = ((String) args[i - start]).getBytes(StandardCharsets.UTF_8); + } else { + bs[i] = JsonConvert.root().convertToBytes(args[i - start]); + } + } + } else { + for (int i = start; i < bs.length; i++) { + bs[i] = String.valueOf(args[i]).getBytes(StandardCharsets.UTF_8); + } + } + /*for (int i = start; i < bs.length; i++) { + bs[i] = JsonConvert.root().convertToBytes(args[i-1]); + }*/ + return client.connect().thenCompose(conn -> conn.writeRequest(conn.pollRequest(WorkThread.currWorkThread()).prepare(command, key, bs))).orTimeout(6, TimeUnit.SECONDS); + } + + @Local + public CompletableFuture sendAsync(final String command, final String key, final byte[]... args) { + return client.connect().thenCompose(conn -> conn.writeRequest(conn.pollRequest(WorkThread.currWorkThread()).prepare(command, key, args))).orTimeout(6, TimeUnit.SECONDS); + } + + private byte[][] keySetArgs(String key) { + return new byte[][]{key.getBytes(StandardCharsets.UTF_8)}; + } + + private byte[][] keyListArgs(String key) { + return new byte[][]{key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}}; + } + + private byte[][] keyArgs(boolean set, String key) { + if (set) { + return new byte[][]{key.getBytes(StandardCharsets.UTF_8)}; + } + return new byte[][]{key.getBytes(StandardCharsets.UTF_8), new byte[]{'0'}, new byte[]{'-', '1'}}; + } + + private byte[] formatValue(long value) { + return String.valueOf(value).getBytes(StandardCharsets.UTF_8); + } + + private byte[] formatValue(String key, RedisCryptor cryptor, String value) { + if (cryptor != null) { + value = cryptor.encrypt(key, value); + } + if (value == null) { + throw new NullPointerException(); + } + return value.getBytes(StandardCharsets.UTF_8); + } + + private byte[] formatValue(String key, RedisCryptor cryptor, Object value) { + return formatValue(key, cryptor, null, null, value); + } + + private byte[] formatValue(String key, RedisCryptor cryptor, Convert convert0, Type type, Object value) { + if (value == null) { + throw new NullPointerException(); + } + if (value instanceof Boolean) { + return (Boolean) value ? RedisCacheRequest.TRUE : RedisCacheRequest.FALSE; + } + if (value instanceof byte[]) { + if (cryptor != null) { + String val = cryptor.encrypt(key, new String((byte[]) value, StandardCharsets.UTF_8)); + return val.getBytes(StandardCharsets.UTF_8); + } + return (byte[]) value; + } + if (value instanceof CharSequence) { + if (cryptor != null) { + value = cryptor.encrypt(key, String.valueOf(value)); + } + return String.valueOf(value).getBytes(StandardCharsets.UTF_8); + } + if (value.getClass().isPrimitive() || Number.class.isAssignableFrom(value.getClass())) { + return String.valueOf(value).getBytes(StandardCharsets.US_ASCII); + } + if (convert0 == null) { + if (convert == null) { //compile模式下convert可能为null + convert = JsonConvert.root(); + } + convert0 = convert; + } + byte[] bs = convert0.convertToBytes(type == null ? value.getClass() : type, value); + if (cryptor != null) { + String val = cryptor.encrypt(key, new String(bs, StandardCharsets.UTF_8)); + return val.getBytes(StandardCharsets.UTF_8); + } + return bs; + } + + @Override + public CompletableFuture>> getCollectionMapAsync(final boolean set, final Type componentType, final String... keys) { + final CompletableFuture>> rsFuture = new CompletableFuture<>(); + final Map> map = new LinkedHashMap<>(); + final ReentrantLock mapLock = new ReentrantLock(); + final CompletableFuture[] futures = new CompletableFuture[keys.length]; + for (int i = 0; i < keys.length; i++) { + final String key = keys[i]; + futures[i] = sendAsync(set ? "SMEMBERS" : "LRANGE", key, keyArgs(set, key)).thenAccept(v -> { + Collection c = set ? v.getSetValue(key, cryptor, componentType) : v.getListValue(key, cryptor, componentType); + if (c != null) { + mapLock.lock(); + try { + map.put(key, (Collection) c); + } finally { + mapLock.unlock(); + } + } + }); + } + CompletableFuture.allOf(futures).whenComplete((w, e) -> { + if (e != null) { + rsFuture.completeExceptionally(e); + } else { + rsFuture.complete(map); + } + }); + return rsFuture; + } + + @Override + public CompletableFuture getCollectionSizeAsync(String key) { + return sendAsync("TYPE", key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { + String type = t.getStringValue(key, cryptor); + if (type == null) { + return CompletableFuture.completedFuture(0); + } + return sendAsync(type.contains("list") ? "LLEN" : "SCARD", key, key.getBytes(StandardCharsets.UTF_8)).thenApply(v -> v.getIntValue(0)); + }); + } + + @Override + public int getCollectionSize(String key) { + return getCollectionSizeAsync(key).join(); + } + + @Override + public CompletableFuture> getCollectionAsync(String key, final Type componentType) { + return sendAsync("TYPE", key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { + String type = t.getStringValue(key, cryptor); + if (type == null) { + return CompletableFuture.completedFuture(null); + } + boolean set = !type.contains("list"); + return sendAsync(set ? "SMEMBERS" : "LRANGE", key, keyArgs(set, key)).thenApply(v -> set ? v.getSetValue(key, cryptor, componentType) : v.getListValue(key, cryptor, componentType)); + }); + } + + @Override + public CompletableFuture getLongArrayAsync(String... keys) { + byte[][] bs = new byte[keys.length][]; + for (int i = 0; i < bs.length; i++) { + bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); + } + return sendAsync("MGET", keys[0], bs).thenApply(v -> { + List list = (List) v.getListValue(keys[0], cryptor, long.class); + Long[] rs = new Long[keys.length]; + for (int i = 0; i < keys.length; i++) { + Number obj = (Number) list.get(i); + rs[i] = obj == null ? null : obj.longValue(); + } + return rs; + }); + } + + @Override + public CompletableFuture getStringArrayAsync(String... keys) { + byte[][] bs = new byte[keys.length][]; + for (int i = 0; i < bs.length; i++) { + bs[i] = keys[i].getBytes(StandardCharsets.UTF_8); + } + return sendAsync("MGET", keys[0], bs).thenApply(v -> { + List list = (List) v.getListValue(keys[0], cryptor, String.class); + String[] rs = new String[keys.length]; + for (int i = 0; i < keys.length; i++) { + Object obj = list.get(i); + rs[i] = obj == null ? null : obj.toString(); + } + return rs; + }); + } + + @Override + public Collection getCollection(String key, final Type componentType) { + return (Collection) getCollectionAsync(key, componentType).join(); + } + + @Override + public Long[] getLongArray(final String... keys) { + return getLongArrayAsync(keys).join(); + } + + @Override + public String[] getStringArray(final String... keys) { + return getStringArrayAsync(keys).join(); + } + + @Override + public CompletableFuture> getStringCollectionAsync(String key) { + return sendAsync("TYPE", key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { + String type = t.getStringValue(key, cryptor); + if (type == null) { + return CompletableFuture.completedFuture(null); + } + boolean set = !type.contains("list"); + return sendAsync(set ? "SMEMBERS" : "LRANGE", key, keyArgs(set, key)).thenApply(v -> set ? v.getSetValue(key, cryptor, String.class) : v.getListValue(key, cryptor, String.class)); + }); + } + + @Override + public CompletableFuture>> getStringCollectionMapAsync(final boolean set, String... keys) { + final CompletableFuture>> rsFuture = new CompletableFuture<>(); + final Map> map = new LinkedHashMap<>(); + final ReentrantLock mapLock = new ReentrantLock(); + final CompletableFuture[] futures = new CompletableFuture[keys.length]; + for (int i = 0; i < keys.length; i++) { + final String key = keys[i]; + futures[i] = sendAsync(set ? "SMEMBERS" : "LRANGE", key, keyArgs(set, key)).thenAccept(v -> { + Collection c = set ? v.getSetValue(key, cryptor, String.class) : v.getListValue(key, cryptor, String.class); + if (c != null) { + mapLock.lock(); + try { + map.put(key, (Collection) c); + } finally { + mapLock.unlock(); + } + } + }); + } + CompletableFuture.allOf(futures).whenComplete((w, e) -> { + if (e != null) { + rsFuture.completeExceptionally(e); + } else { + rsFuture.complete(map); + } + }); + return rsFuture; + } + + @Override + public Collection getStringCollection(String key) { + return getStringCollectionAsync(key).join(); + } + + @Override + public Map> getStringCollectionMap(final boolean set, String... keys) { + return getStringCollectionMapAsync(set, keys).join(); + } + + @Override + public CompletableFuture> getLongCollectionAsync(String key) { + return sendAsync("TYPE", key, key.getBytes(StandardCharsets.UTF_8)).thenCompose(t -> { + String type = t.getStringValue(key, cryptor); + if (type == null) { + return CompletableFuture.completedFuture(null); + } + boolean set = !type.contains("list"); + return sendAsync(set ? "SMEMBERS" : "LRANGE", key, keyArgs(set, key)).thenApply(v -> set ? v.getSetValue(key, cryptor, long.class) : v.getListValue(key, cryptor, long.class)); + }); + } + + @Override + public CompletableFuture>> getLongCollectionMapAsync(final boolean set, String... keys) { + final CompletableFuture>> rsFuture = new CompletableFuture<>(); + final Map> map = new LinkedHashMap<>(); + final ReentrantLock mapLock = new ReentrantLock(); + final CompletableFuture[] futures = new CompletableFuture[keys.length]; + for (int i = 0; i < keys.length; i++) { + final String key = keys[i]; + futures[i] = sendAsync(set ? "SMEMBERS" : "LRANGE", key, keyArgs(set, key)).thenAccept(v -> { + Collection c = set ? v.getSetValue(key, cryptor, long.class) : v.getListValue(key, cryptor, long.class); + if (c != null) { + mapLock.lock(); + try { + map.put(key, (Collection) c); + } finally { + mapLock.unlock(); + } + } + }); + } + CompletableFuture.allOf(futures).whenComplete((w, e) -> { + if (e != null) { + rsFuture.completeExceptionally(e); + } else { + rsFuture.complete(map); + } + }); + return rsFuture; + } + + @Override + public Collection getLongCollection(String key) { + return getLongCollectionAsync(key).join(); + } + + @Override + public Map> getLongCollectionMap(final boolean set, String... keys) { + return getLongCollectionMapAsync(set, keys).join(); + } + + //--------------------- getexCollection ------------------------------ + @Override + public CompletableFuture> getexCollectionAsync(String key, int expireSeconds, final Type componentType) { + return (CompletableFuture) expireAsync(key, expireSeconds).thenCompose(v -> getCollectionAsync(key, componentType)); + } + + @Override + public Collection getexCollection(String key, final int expireSeconds, final Type componentType) { + return (Collection) getexCollectionAsync(key, expireSeconds, componentType).join(); + } + + @Override + public CompletableFuture> getexStringCollectionAsync(String key, int expireSeconds) { + return (CompletableFuture) expireAsync(key, expireSeconds).thenCompose(v -> getStringCollectionAsync(key)); + } + + @Override + public Collection getexStringCollection(String key, final int expireSeconds) { + return getexStringCollectionAsync(key, expireSeconds).join(); + } + + @Override + public CompletableFuture> getexLongCollectionAsync(String key, int expireSeconds) { + return (CompletableFuture) expireAsync(key, expireSeconds).thenCompose(v -> getLongCollectionAsync(key)); + } + + @Override + public Collection getexLongCollection(String key, final int expireSeconds) { + return getexLongCollectionAsync(key, expireSeconds).join(); + } + + @Override + public Map> getCollectionMap(final boolean set, final Type componentType, String... keys) { + return (Map) getCollectionMapAsync(set, componentType, keys).join(); + } + + private static Function passwordDecoder = null; + + public static void setPasswordDecoder(Function decoder) { + passwordDecoder = decoder; + } +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCacheSourceProvider.java b/src/main/java/org/redkalex/cache/redis/RedisCacheSourceProvider.java new file mode 100644 index 0000000..3bf7f92 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCacheSourceProvider.java @@ -0,0 +1,29 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkalex.cache.redis; + +import org.redkale.annotation.Priority; +import org.redkale.source.CacheSource; +import org.redkale.source.CacheSourceProvider; +import org.redkale.util.AnyValue; + +/** + * @author zhangjx + */ +@Priority(1) +public class RedisCacheSourceProvider implements CacheSourceProvider { + + @Override + public boolean acceptsConf(AnyValue config) { + return new MyRedisCacheSource().acceptsConf(config); + } + + @Override + public CacheSource createInstance() { + return new MyRedisCacheSource(); + } + +} diff --git a/src/main/java/org/redkalex/cache/redis/RedisCryptor.java b/src/main/java/org/redkalex/cache/redis/RedisCryptor.java new file mode 100644 index 0000000..96f6ee6 --- /dev/null +++ b/src/main/java/org/redkalex/cache/redis/RedisCryptor.java @@ -0,0 +1,46 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package org.redkalex.cache.redis; + +import org.redkale.util.AnyValue; + +/** + * @author zhangjx + */ +public interface RedisCryptor { + + /** + * 初始化 + * + * @param conf 配置 + */ + public void init(AnyValue conf); + + /** + * 加密, 无需加密的key对应的值需要直接返回value + * + * @param key key + * @param value 明文 + * @return 密文 + */ + public String encrypt(String key, String value); + + /** + * 解密, 无需解密的key对应的值需要直接返回value + * + * @param key key + * @param value 密文 + * @return 明文 + */ + public String decrypt(String key, String value); + + /** + * 销毁 + * + * @param conf 配置 + */ + public void destroy(AnyValue conf); + +} diff --git a/test/com/zdemo/test/MyConsumer.java b/test/com/zdemo/test/MyConsumer.java deleted file mode 100644 index 0bfef54..0000000 --- a/test/com/zdemo/test/MyConsumer.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zdemo.test; - -import com.zdemo.zhub.ZHubClient; - -public class MyConsumer extends ZHubClient { - - public String getGroupid() { - return "group-test"; //消费组名称 - } - - @Override - protected boolean preInit() { - return true; - } -} diff --git a/test/com/zdemo/test/AppTest.java b/test/net.tccn/mq/AppTest.java similarity index 90% rename from test/com/zdemo/test/AppTest.java rename to test/net.tccn/mq/AppTest.java index 428bb92..640f3d3 100644 --- a/test/com/zdemo/test/AppTest.java +++ b/test/net.tccn/mq/AppTest.java @@ -1,11 +1,8 @@ -package com.zdemo.test; +package net.tccn.mq; -import com.zdemo.Event; -import com.zdemo.IProducer; -import com.zdemo.zhub.Delays; +import net.tccn.Event; import net.tccn.timer.Timers; import org.junit.Test; -import org.redkale.boot.Application; import org.redkale.convert.json.JsonConvert; import java.util.ArrayList; @@ -33,13 +30,6 @@ public class AppTest { System.out.println(str.length()); - //启动并开启消费监听 - MyConsumer consumer = Application.singleton(MyConsumer.class); - - consumer.subscribe("a", strx -> { - logger.info("我收到了消息 a 事件:" + str); - }); - /*consumer.timer("a", () -> { System.out.println(Utility.now() + " timer a 执行了"); try { @@ -83,20 +73,7 @@ public class AppTest { @Test public void runProducer() { - try { - MyConsumer producer = Application.singleton(MyConsumer.class); - for (int i = 0; i < 10_0000; i++) { - producer.publish("a-1", i); - } - try { - Thread.sleep(1_000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } catch (Exception e) { - e.printStackTrace(); - } } private static LinkedBlockingQueue queue = new LinkedBlockingQueue(); @@ -148,21 +125,6 @@ public class AppTest { System.out.println(fun.toString()); } - @Test - public void yy() { - IProducer producer = null; - try { - producer = Application.singleton(MyConsumer.class); - - for (int i = 0; i < 100; i++) { - - producer.publish("x", "x"); - Thread.sleep(1000); - } - } catch (Exception e) { - e.printStackTrace(); - } - } // (27+5*23)/(63-59) // [27+5*23] [/] [63-59] @@ -380,10 +342,10 @@ public class AppTest { @Test public void delay() { - DelayQueue delayQueue = new DelayQueue<>(); + DelayQueue delayQueue = new DelayQueue<>(); logger.info("加入延时任务1"); - delayQueue.add(new Delays(5000, () -> { + delayQueue.add(new com.zdemo.zhub.Delays(5000, () -> { logger.info("任务1 延时任务执行了!"); })); @@ -394,13 +356,13 @@ public class AppTest { } logger.info("加入延时任务2"); - delayQueue.add(new Delays(5000, () -> { + delayQueue.add(new com.zdemo.zhub.Delays(5000, () -> { logger.info("任务2 延时任务执行了!"); })); try { while (true) { - Delays delay = delayQueue.take(); + com.zdemo.zhub.Delays delay = delayQueue.take(); delay.run(); } diff --git a/test/com/zdemo/test/Delays.java b/test/net.tccn/mq/Delays.java similarity index 100% rename from test/com/zdemo/test/Delays.java rename to test/net.tccn/mq/Delays.java diff --git a/test/com/zdemo/test/HelloService.java b/test/net.tccn/mq/HelloService.java similarity index 91% rename from test/com/zdemo/test/HelloService.java rename to test/net.tccn/mq/HelloService.java index 9e46d6e..c5d0171 100644 --- a/test/com/zdemo/test/HelloService.java +++ b/test/net.tccn/mq/HelloService.java @@ -1,8 +1,8 @@ -package com.zdemo.test; +package net.tccn.mq; -import com.zdemo.IType; -import com.zdemo.zhub.RpcResult; -import com.zdemo.zhub.ZHubClient; +import net.tccn.IType; +import net.tccn.zhub.RpcResult; +import net.tccn.zhub.ZHubClient; import org.redkale.net.http.RestMapping; import org.redkale.net.http.RestService; import org.redkale.service.Service; @@ -15,22 +15,28 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; -@RestService(automapping = true) +@RestService(automapping = true, name = "hello") public class HelloService implements Service { - @Resource(name = "zhub") + @Resource(name = "hub") private ZHubClient zhub; - private net.tccn.zhub.ZHubClient zhubx = null; + /*@Resource(name = "hubx") + private ZHubClient zhubx; + + @Resource(name = "vvvvhub2") + private ZHubClient zhub2;*/ + + //private net.tccn.zhub.ZHubClient zhubx = null; @Override public void init(AnyValue config) { - CompletableFuture.runAsync(() -> { + /*CompletableFuture.runAsync(() -> { zhubx = new net.tccn.zhub.ZHubClient("127.0.0.1", 1216, "g-dev", "DEV-LOCAL"); //zhubx = new net.tccn.zhub.ZHubClient("47.111.150.118", 6066, "g-dev", "DEV-LOCAL"); - }); + });*/ // Function, RpcResult> fun /*zhub.rpcSubscribe("x", new TypeToken() { @@ -41,13 +47,13 @@ public class HelloService implements Service { zhub.rpcSubscribe("y", new TypeToken() { }, r -> { - return r.buildResp(Map.of("v", r.getValue().toUpperCase() + ": Ok")); + return r.render(Map.of("v", r.getValue().toUpperCase() + ": Ok")); }); zhub.subscribe("sport:reqtime", x -> { System.out.println(x); }); - zhub.subscribe("abx", x -> { + zhub.subscribe("abx1", x -> { System.out.println(x); }); @@ -111,8 +117,8 @@ public class HelloService implements Service { /*RpcResult x = zhub.rpc("rpc:file:up-token", Map.of(), new TypeToken<>() { });*/ - net.tccn.zhub.RpcResult x = zhubx.rpc("y", v + i, new com.google.gson.reflect.TypeToken<>() { - }); + /*RpcResult x = zhubx.rpc("y", v + i, new com.google.gson.reflect.TypeToken<>() { + });*/ System.out.println("time: " + (System.currentTimeMillis() - start) + " ms"); @@ -122,6 +128,12 @@ public class HelloService implements Service { return "ok"; } + @RestMapping(name = "send") + public String send() { + zhub.publish("abx1", 1); + return "ok"; + } + public static void main(String[] args) { // "\"别人家的女娃子\uD83E\uDD1E\uD83C\uDFFB\""