Compare commits
7 Commits
master
...
dev/redkal
Author | SHA1 | Date | |
---|---|---|---|
efdf42c4f2 | |||
4d125f8e46 | |||
8a5f1c10e1 | |||
9d23c84cba | |||
ff3d877a37 | |||
2e0d9af014 | |||
747b165e77 |
37
pom.xml
37
pom.xml
@ -4,9 +4,9 @@
|
|||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>net.tccn</groupId>
|
<groupId>dev.zhub</groupId>
|
||||||
<artifactId>zhub-client-redkale</artifactId>
|
<artifactId>zhub-client-redkale</artifactId>
|
||||||
<version>0.1.2-dev</version>
|
<version>x.1.1.dev</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
@ -14,30 +14,33 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.redkale</groupId>
|
|
||||||
<artifactId>redkale</artifactId>
|
|
||||||
<version>2.8.0-dev</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>maven-nexus</id>
|
<id>maven-release</id>
|
||||||
<name>maven-nexus</name>
|
<name>maven-nexus</name>
|
||||||
<url>http://47.106.237.198:8081/repository/maven-public/</url>
|
<url>https://nexus.1216.top/repository/maven-public/</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<repository>
|
<repository>
|
||||||
<id>mvn-release</id>
|
<id>mvn-release</id>
|
||||||
<name>mvn-release</name>
|
<name>mvn-release</name>
|
||||||
<url>http://47.106.237.198:8081/repository/maven-releases/</url>
|
<url>https://nexus.1216.top/repository/maven-releases/</url>
|
||||||
</repository>
|
</repository>
|
||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.redkale</groupId>
|
||||||
|
<artifactId>redkale</artifactId>
|
||||||
|
<version>2.8.0.dev</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.13.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
</project>
|
</project>
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn;
|
package dev.zhub;
|
||||||
|
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
import org.redkale.util.Resourcable;
|
import org.redkale.util.Resourcable;
|
||||||
@ -19,7 +19,7 @@ public abstract class AbstractConsumer extends ZhubAgentProvider implements ICon
|
|||||||
|
|
||||||
protected static String APP_NAME = "";
|
protected static String APP_NAME = "";
|
||||||
|
|
||||||
private Map<String, EventType> eventMap = new ConcurrentHashMap<>();
|
protected Map<String, EventType<?>> eventMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
protected abstract String getGroupid();
|
protected abstract String getGroupid();
|
||||||
|
|
||||||
@ -31,6 +31,7 @@ public abstract class AbstractConsumer extends ZhubAgentProvider implements ICon
|
|||||||
return Set.of("-");
|
return Set.of("-");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// topic 消息消费前处理
|
||||||
protected void accept(String topic, String value) {
|
protected void accept(String topic, String value) {
|
||||||
EventType eventType = eventMap.get(topic);
|
EventType eventType = eventMap.get(topic);
|
||||||
|
|
||||||
@ -44,6 +45,12 @@ public abstract class AbstractConsumer extends ZhubAgentProvider implements ICon
|
|||||||
eventType.accept(data);
|
eventType.accept(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rpc 被调用端
|
||||||
|
protected <T> void rpcAccept(String topic, T value) {
|
||||||
|
EventType eventType = eventMap.get(topic);
|
||||||
|
eventType.accept(value);
|
||||||
|
}
|
||||||
|
|
||||||
protected final void removeEventType(String topic) {
|
protected final void removeEventType(String topic) {
|
||||||
eventMap.remove(topic);
|
eventMap.remove(topic);
|
||||||
}
|
}
|
||||||
@ -77,4 +84,13 @@ public abstract class AbstractConsumer extends ZhubAgentProvider implements ICon
|
|||||||
public String resourceName() {
|
public String resourceName() {
|
||||||
return super.getName();
|
return super.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String toStr(Object v) {
|
||||||
|
if (v instanceof String) {
|
||||||
|
return (String) v;
|
||||||
|
} else if (v == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return convert.convertTo(v);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn;
|
package dev.zhub;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发布订阅 事件
|
* 发布订阅 事件
|
||||||
@ -15,8 +15,8 @@ public class Event<V> {
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <V> Event of(String topic, V value) {
|
public static <V> Event<V> of(String topic, V value) {
|
||||||
return new Event<V>(topic, value);
|
return new Event<>(topic, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn;
|
package dev.zhub;
|
||||||
|
|
||||||
import org.redkale.util.TypeToken;
|
import org.redkale.util.TypeToken;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn;
|
package dev.zhub;
|
||||||
|
|
||||||
import org.redkale.util.TypeToken;
|
import org.redkale.util.TypeToken;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn;
|
package dev.zhub;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn;
|
package dev.zhub;
|
||||||
|
|
||||||
import org.redkale.util.TypeToken;
|
import org.redkale.util.TypeToken;
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
package net.tccn;
|
package dev.zhub;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
import org.redkale.net.AsyncIOGroup;
|
import org.redkale.net.AsyncIOGroup;
|
||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
import org.redkale.util.ResourceFactory;
|
import org.redkale.util.ResourceFactory;
|
||||||
@ -12,9 +13,65 @@ public class RedisTest {
|
|||||||
|
|
||||||
static MyRedisCacheSource source = new MyRedisCacheSource();
|
static MyRedisCacheSource source = new MyRedisCacheSource();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void keyTest() {
|
||||||
|
source.set("a", 3);
|
||||||
|
System.out.println(source.get("a"));
|
||||||
|
source.del("a");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ax:false
|
||||||
|
* ax:true
|
||||||
|
* ax:false
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void bitTest() {
|
||||||
|
boolean ax = source.getBit("ax", 6);
|
||||||
|
System.out.println("ax:"+ ax); // false
|
||||||
|
source.setBit("ax", 6, true);
|
||||||
|
|
||||||
|
ax = source.getBit("ax", 6);
|
||||||
|
System.out.println("ax:"+ ax); // true
|
||||||
|
|
||||||
|
source.setBit("ax", 6, false);
|
||||||
|
ax = source.getBit("ax", 6);
|
||||||
|
System.out.println("ax:"+ ax); // false
|
||||||
|
source.del("ax");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setTest() {
|
||||||
|
source.del("setx");
|
||||||
|
source.sadd("setx", int.class, 1, 2, 3, 5, 6);
|
||||||
|
int setx = source.spop("setx", int.class);
|
||||||
|
System.out.println(setx);
|
||||||
|
|
||||||
|
setx = source.spop("setx", int.class);
|
||||||
|
System.out.println(setx);
|
||||||
|
source.del("setx");
|
||||||
|
|
||||||
|
|
||||||
|
source.srem("setx", int.class,213, 2312);
|
||||||
|
|
||||||
|
/*//source.sadd("setx", list.toArray(Integer[]::new));
|
||||||
|
List<Integer> 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));*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static { // redis://:*Zhong9307!@47.111.150.118:6064?db=2
|
static { // redis://:*Zhong9307!@47.111.150.118:6064?db=2
|
||||||
AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue().addValue(CACHE_SOURCE_MAXCONNS, "1");
|
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"));
|
conf.addValue(CACHE_SOURCE_NODES, "redis://:123456@127.0.0.1:6379?db=0");
|
||||||
|
|
||||||
final ResourceFactory factory = ResourceFactory.create();
|
final ResourceFactory factory = ResourceFactory.create();
|
||||||
final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16);
|
final AsyncIOGroup asyncGroup = new AsyncIOGroup(8192, 16);
|
||||||
asyncGroup.start();
|
asyncGroup.start();
|
||||||
@ -23,22 +80,6 @@ public class RedisTest {
|
|||||||
//source.defaultConvert = JsonFactory.root().getConvert();
|
//source.defaultConvert = JsonFactory.root().getConvert();
|
||||||
source.init(conf);
|
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.lock("lockx", 5000);
|
||||||
@ -52,67 +93,15 @@ public class RedisTest {
|
|||||||
int i = (short) 3;
|
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 ------------------------------
|
//--------------------- set ------------------------------
|
||||||
/*source.del("setx");
|
/*
|
||||||
*//*
|
*/
|
||||||
int[] ints = {1, 2, 3};
|
|
||||||
source.sadd("setx", ints);
|
/*
|
||||||
*//*
|
|
||||||
|
|
||||||
//source.sadd("setx", list.toArray(Integer[]::new));
|
|
||||||
List<Integer> 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<String> setx1 = source.getCollection("setx", String.class);
|
Collection<String> setx1 = source.getCollection("setx", String.class);
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn;
|
package dev.zhub;
|
||||||
|
|
||||||
import org.redkale.boot.Application;
|
import org.redkale.boot.Application;
|
||||||
import org.redkale.boot.NodeServer;
|
import org.redkale.boot.NodeServer;
|
||||||
@ -8,7 +8,6 @@ import org.redkale.service.Service;
|
|||||||
import org.redkale.util.ResourceEvent;
|
import org.redkale.util.ResourceEvent;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@ -29,11 +28,6 @@ public abstract class ZhubAgentProvider extends ClusterAgent {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<Map<String, Set<InetSocketAddress>>> queryMqtpAddress(String protocol, String module, String resname) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Set<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname) {
|
public CompletableFuture<Set<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname) {
|
||||||
return null;
|
return null;
|
@ -1,6 +1,6 @@
|
|||||||
package net.tccn;
|
package dev.zhub;
|
||||||
|
|
||||||
import net.tccn.zhub.ZHubClient;
|
import dev.zhub.client.ZHubClient;
|
||||||
import org.redkale.annotation.Priority;
|
import org.redkale.annotation.Priority;
|
||||||
import org.redkale.cluster.ClusterAgent;
|
import org.redkale.cluster.ClusterAgent;
|
||||||
import org.redkale.cluster.ClusterAgentProvider;
|
import org.redkale.cluster.ClusterAgentProvider;
|
@ -1,11 +1,12 @@
|
|||||||
package net.tccn.zhub;
|
package dev.zhub.client;
|
||||||
|
|
||||||
// ================================================== lock ==================================================
|
// ================================================== lock ==================================================
|
||||||
public class Lock {
|
public class Lock {
|
||||||
private String name;
|
protected String name;
|
||||||
private String uuid;
|
protected String uuid;
|
||||||
private int duration;
|
protected int duration;
|
||||||
private ZHubClient hubClient;
|
protected boolean success;
|
||||||
|
protected ZHubClient hubClient;
|
||||||
|
|
||||||
protected Lock(String name, String uuid, int duration, ZHubClient hubClient) {
|
protected Lock(String name, String uuid, int duration, ZHubClient hubClient) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -17,4 +18,8 @@ public class Lock {
|
|||||||
public void unLock() {
|
public void unLock() {
|
||||||
hubClient.send("unlock", name, uuid);
|
hubClient.send("unlock", name, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean success() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,8 +1,9 @@
|
|||||||
package net.tccn.zhub;
|
package dev.zhub.client;
|
||||||
|
|
||||||
import org.redkale.convert.ConvertColumn;
|
import org.redkale.convert.ConvertColumn;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
|
||||||
import org.redkale.service.RetResult;
|
import org.redkale.service.RetResult;
|
||||||
|
import org.redkale.util.TypeToken;
|
||||||
|
import org.redkale.util.Utility;
|
||||||
|
|
||||||
public class Rpc<T> {
|
public class Rpc<T> {
|
||||||
private String ruk; // request unique key:
|
private String ruk; // request unique key:
|
||||||
@ -11,13 +12,15 @@ public class Rpc<T> {
|
|||||||
|
|
||||||
private RpcResult rpcResult;
|
private RpcResult rpcResult;
|
||||||
|
|
||||||
|
private TypeToken typeToken;
|
||||||
|
|
||||||
public Rpc() {
|
public Rpc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Rpc(String appname, String ruk, String topic, Object value) {
|
protected Rpc(String appname, String topic, T value) {
|
||||||
this.ruk = appname + "::" + ruk;
|
this.ruk = appname + "::" + Utility.uuid();
|
||||||
this.topic = topic;
|
this.topic = topic;
|
||||||
this.value = (T) JsonConvert.root().convertTo(value);
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRuk() {
|
public String getRuk() {
|
||||||
@ -53,6 +56,16 @@ public class Rpc<T> {
|
|||||||
this.rpcResult = rpcResult;
|
this.rpcResult = rpcResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ConvertColumn(ignore = true)
|
||||||
|
public TypeToken getTypeToken() {
|
||||||
|
return typeToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConvertColumn(ignore = true)
|
||||||
|
public void setTypeToken(TypeToken typeToken) {
|
||||||
|
this.typeToken = typeToken;
|
||||||
|
}
|
||||||
|
|
||||||
@ConvertColumn(ignore = true)
|
@ConvertColumn(ignore = true)
|
||||||
public String getBackTopic() {
|
public String getBackTopic() {
|
||||||
return ruk.split("::")[0];
|
return ruk.split("::")[0];
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn.zhub;
|
package dev.zhub.client;
|
||||||
|
|
||||||
public class RpcResult<R> {
|
public class RpcResult<R> {
|
||||||
private String ruk;
|
private String ruk;
|
@ -1,7 +1,7 @@
|
|||||||
package net.tccn.zhub;
|
package dev.zhub.client;
|
||||||
|
|
||||||
import net.tccn.*;
|
import dev.zhub.*;
|
||||||
import net.tccn.timer.Timers;
|
import dev.zhub.timer.Timers;
|
||||||
import org.redkale.annotation.AutoLoad;
|
import org.redkale.annotation.AutoLoad;
|
||||||
import org.redkale.annotation.ResourceType;
|
import org.redkale.annotation.ResourceType;
|
||||||
import org.redkale.service.Local;
|
import org.redkale.service.Local;
|
||||||
@ -9,7 +9,6 @@ import org.redkale.service.Service;
|
|||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
import org.redkale.util.Comment;
|
import org.redkale.util.Comment;
|
||||||
import org.redkale.util.TypeToken;
|
import org.redkale.util.TypeToken;
|
||||||
import org.redkale.util.Utility;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -18,10 +17,7 @@ import java.io.OutputStream;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -44,17 +40,11 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
private BufferedReader reader;
|
private BufferedReader reader;
|
||||||
|
|
||||||
private final LinkedBlockingQueue<Timer> timerQueue = new LinkedBlockingQueue<>();
|
private final LinkedBlockingQueue<Timer> timerQueue = new LinkedBlockingQueue<>();
|
||||||
private final LinkedBlockingQueue<Event<String>> topicQueue = new LinkedBlockingQueue<>();
|
private final LinkedBlockingQueue<Event<String>> topicQueue = new LinkedBlockingQueue<>(); // [=> Object]
|
||||||
private final LinkedBlockingQueue<Event<String>> rpcBackQueue = new LinkedBlockingQueue<>(); // RPC BACK MSG
|
private final LinkedBlockingQueue<Event<Object>> rpcBackQueue = new LinkedBlockingQueue<>(); // RPC BACK MSG [=> Object]
|
||||||
private final LinkedBlockingQueue<Event<String>> rpcCallQueue = new LinkedBlockingQueue<>(); // RPC CALL MSG
|
private final LinkedBlockingQueue<Event<Object>> rpcCallQueue = new LinkedBlockingQueue<>(); // RPC CALL MSG [=> Object]
|
||||||
private final LinkedBlockingQueue<String> sendMsgQueue = new LinkedBlockingQueue<>(); // SEND MSG
|
private final LinkedBlockingQueue<String> sendMsgQueue = new LinkedBlockingQueue<>(); // SEND MSG
|
||||||
|
|
||||||
/*private BiConsumer<Runnable, Integer> threadBuilder = (r, n) -> {
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
new Thread(() -> r.run()).start();
|
|
||||||
}
|
|
||||||
};*/
|
|
||||||
|
|
||||||
private static Map<String, ZHubClient> mainHub = new HashMap<>(); // 127.0.0.1:1216 - ZHubClient
|
private static Map<String, ZHubClient> mainHub = new HashMap<>(); // 127.0.0.1:1216 - ZHubClient
|
||||||
|
|
||||||
public ZHubClient() {
|
public ZHubClient() {
|
||||||
@ -109,12 +99,11 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
}
|
}
|
||||||
|
|
||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() -> {
|
||||||
|
if (!initSocket(0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 消息 事件接收
|
// 消息 事件接收
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
if (!initSocket(0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
String readLine = reader.readLine();
|
String readLine = reader.readLine();
|
||||||
@ -148,7 +137,7 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
|
|
||||||
String value = "";
|
String value = "";
|
||||||
do {
|
do {
|
||||||
if (value.length() > 0) {
|
if (!value.isEmpty()) {
|
||||||
value += "\r\n";
|
value += "\r\n";
|
||||||
}
|
}
|
||||||
String s = reader.readLine();
|
String s = reader.readLine();
|
||||||
@ -162,11 +151,24 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
Lock lock = lockTag.get(value);
|
Lock lock = lockTag.get(value);
|
||||||
if (lock != null) {
|
if (lock != null) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
|
lock.success = true;
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// trylock msg
|
||||||
|
if ("trylock".equals(topic)) {
|
||||||
|
Lock lock = lockTag.get(value);
|
||||||
|
if (lock != null) {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.success = false;
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// rpc back msg
|
// rpc back msg
|
||||||
if (APP_NAME.equals(topic)) {
|
if (APP_NAME.equals(topic)) {
|
||||||
rpcBackQueue.add(Event.of(topic, value));
|
rpcBackQueue.add(Event.of(topic, value));
|
||||||
@ -215,9 +217,8 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
while (true) {
|
while (true) {
|
||||||
Timer timer = null;
|
Timer timer = null;
|
||||||
try {
|
try {
|
||||||
if ((timer = timerQueue.take()) == null) {
|
timer = timerQueue.take();
|
||||||
return;
|
|
||||||
}
|
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
pool.submit(timer.runnable).get(5, TimeUnit.SECONDS);
|
pool.submit(timer.runnable).get(5, TimeUnit.SECONDS);
|
||||||
long end = System.currentTimeMillis();
|
long end = System.currentTimeMillis();
|
||||||
@ -239,9 +240,7 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
while (true) {
|
while (true) {
|
||||||
Event<String> event = null;
|
Event<String> event = null;
|
||||||
try {
|
try {
|
||||||
if ((event = topicQueue.take()) == null) {
|
event = topicQueue.take();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String topic = event.topic;
|
String topic = event.topic;
|
||||||
String value = event.value;
|
String value = event.value;
|
||||||
@ -249,10 +248,10 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (TimeoutException e) {
|
} catch (TimeoutException e) {
|
||||||
logger.log(Level.SEVERE, "topic[" + event.topic + "] event deal time out: " + 5 + " S, value: " + event.value, e);
|
logger.log(Level.SEVERE, "topic[" + event.topic + "] event deal time out: " + 5 + " S, value: " + toStr(event.value), e);
|
||||||
pool = Executors.newFixedThreadPool(1);
|
pool = Executors.newFixedThreadPool(1);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.WARNING, "topic[" + event.topic + "] event accept error :" + event.value, e);
|
logger.log(Level.WARNING, "topic[" + event.topic + "] event accept error :" + toStr(event.value), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
@ -260,18 +259,16 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
// rpc back ,仅做数据解析,暂无耗时监控
|
// rpc back ,仅做数据解析,暂无耗时监控
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
while (true) {
|
while (true) {
|
||||||
Event<String> event = null;
|
Event<Object> event = null;
|
||||||
try {
|
try {
|
||||||
if ((event = rpcBackQueue.take()) == null) {
|
event = rpcBackQueue.take();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//if (event)
|
//if (event)
|
||||||
logger.finest(String.format("rpc-back:[%s]: %s", event.topic, event.value));
|
logger.finest(String.format("rpc-back:[%s]: %s", event.topic, toStr(event.value)));
|
||||||
rpcAccept(event.value);
|
rpcAccept(event.value);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.WARNING, "rpc-back[" + event.topic + "] event accept error :" + event.value, e);
|
logger.log(Level.WARNING, "rpc-back[" + event.topic + "] event accept error :" + toStr(event.value), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
@ -280,22 +277,21 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
ExecutorService pool = Executors.newFixedThreadPool(1);
|
ExecutorService pool = Executors.newFixedThreadPool(1);
|
||||||
while (true) {
|
while (true) {
|
||||||
Event<String> event = null;
|
Event<Object> event = null;
|
||||||
try {
|
try {
|
||||||
if ((event = rpcCallQueue.take()) == null) {
|
event = rpcCallQueue.take();
|
||||||
continue;
|
|
||||||
}
|
logger.finest(String.format("rpc-call:[%s] %s", event.topic, toStr(event.value)));
|
||||||
logger.finest(String.format("rpc-call:[%s] %s", event.topic, event.value));
|
|
||||||
String topic = event.topic;
|
String topic = event.topic;
|
||||||
String value = event.value;
|
Object value = event.value;
|
||||||
pool.submit(() -> accept(topic, value)).get(5, TimeUnit.SECONDS);
|
pool.submit(() -> rpcAccept(topic, value)).get(5, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (TimeoutException e) {
|
} catch (TimeoutException e) {
|
||||||
logger.log(Level.SEVERE, "topic[" + event.topic + "] event deal time out: " + 5 + " S, value: " + event.value, e);
|
logger.log(Level.SEVERE, "topic[" + event.topic + "] event deal time out: " + 5 + " S, value: " + toStr(event.value), e);
|
||||||
pool = Executors.newFixedThreadPool(1);
|
pool = Executors.newFixedThreadPool(1);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.WARNING, "rpc-call[" + event.topic + "] event accept error :" + event.value, e);
|
logger.log(Level.WARNING, "rpc-call[" + event.topic + "] event accept error :" + toStr(event.value), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
@ -305,9 +301,8 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
while (true) {
|
while (true) {
|
||||||
String msg = null;
|
String msg = null;
|
||||||
try {
|
try {
|
||||||
if ((msg = sendMsgQueue.take()) == null) {
|
msg = sendMsgQueue.take();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// logger.log(Level.FINEST, "send-msg: [" + msg + "]");
|
// logger.log(Level.FINEST, "send-msg: [" + msg + "]");
|
||||||
writer.write(msg.getBytes());
|
writer.write(msg.getBytes());
|
||||||
writer.flush();
|
writer.flush();
|
||||||
@ -392,15 +387,6 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
return str.length();
|
return str.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toStr(Object v) {
|
|
||||||
if (v instanceof String) {
|
|
||||||
return (String) v;
|
|
||||||
} else if (v == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return convert.convertTo(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean initSocket(int retry) {
|
protected boolean initSocket(int retry) {
|
||||||
for (int i = 0; i <= retry; i++) {
|
for (int i = 0; i <= retry; i++) {
|
||||||
try {
|
try {
|
||||||
@ -422,7 +408,7 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
send("auth", auth);
|
send("auth", auth);
|
||||||
send("groupid " + groupid);
|
send("groupid " + groupid);
|
||||||
|
|
||||||
StringBuffer buf = new StringBuffer("subscribe lock");
|
StringBuilder buf = new StringBuilder("subscribe lock trylock");
|
||||||
if (mainHub.containsValue(this)) {
|
if (mainHub.containsValue(this)) {
|
||||||
buf.append(" " + APP_NAME);
|
buf.append(" " + APP_NAME);
|
||||||
}
|
}
|
||||||
@ -436,9 +422,9 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
send("timer", name);
|
send("timer", name);
|
||||||
});
|
});
|
||||||
if (retry > 0) {
|
if (retry > 0) {
|
||||||
logger.warning(String.format("ZHubClient[%s][%s] %s Succeed!", getGroupid(), i + 1, retry > 0 ? "reconnection" : "init"));
|
logger.warning(String.format("ZHubClient[%s][%s] %s Succeed!", getGroupid(), i + 1, "reconnection"));
|
||||||
} else {
|
} else {
|
||||||
logger.fine(String.format("ZHubClient[%s] %s Succeed!", getGroupid(), retry > 0 ? "reconnection" : "init"));
|
logger.fine(String.format("ZHubClient[%s] %s Succeed!", getGroupid(), "init"));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -469,11 +455,15 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean publish(String topic, Object v) {
|
public boolean publish(String topic, Object v) {
|
||||||
|
/*if (eventMap.containsKey(topic)) { // 本地调用
|
||||||
|
topicQueue.add(Event.of(topic, v));
|
||||||
|
return true;
|
||||||
|
}*/
|
||||||
return send("publish", topic, toStr(v));
|
return send("publish", topic, toStr(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(String topic, Object v) {
|
public void broadcast(String topic, Object v) {
|
||||||
send("broadcast", topic, toStr(v));
|
send("broadcast", topic, toStr(v)); // 广播必须走远端模式
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送 publish 主题消息,若多次发送的 topic + "-" + value 相同,将会做延时重置
|
// 发送 publish 主题消息,若多次发送的 topic + "-" + value 相同,将会做延时重置
|
||||||
@ -527,32 +517,35 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
// ================================================== lock ==================================================
|
// ================================================== lock ==================================================
|
||||||
private Map<String, Lock> lockTag = new ConcurrentHashMap<>();
|
private Map<String, Lock> lockTag = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试加锁,立即返回,
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param duration
|
||||||
|
* @return Lock: lock.success 锁定是否成功标识
|
||||||
|
*/
|
||||||
public Lock tryLock(String key, int duration) {
|
public Lock tryLock(String key, int duration) {
|
||||||
String uuid = Utility.uuid();
|
return lock("trylock", key, duration);
|
||||||
Lock lock = new Lock(key, uuid, duration, this);
|
|
||||||
lockTag.put(uuid, lock);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// c.send("lock", key, uuid, strconv.Itoa(duration))
|
|
||||||
send("lock", key, uuid, String.valueOf(duration));
|
|
||||||
synchronized (lock) {
|
|
||||||
lock.wait();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return lock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 为替换 tryLock 方法做过度准确
|
|
||||||
public Lock lock(String key, int duration) {
|
public Lock lock(String key, int duration) {
|
||||||
String uuid = Utility.uuid();
|
return lock("lock", key, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cmd lock|trylock
|
||||||
|
* @param key 加锁 key
|
||||||
|
* @param duration 锁定时长
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Lock lock(String cmd, String key, int duration) {
|
||||||
|
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
|
||||||
Lock lock = new Lock(key, uuid, duration, this);
|
Lock lock = new Lock(key, uuid, duration, this);
|
||||||
lockTag.put(uuid, lock);
|
lockTag.put(uuid, lock);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// c.send("lock", key, uuid, strconv.Itoa(duration))
|
// c.send("lock", key, uuid, strconv.Itoa(duration))
|
||||||
send("lock", key, uuid, String.valueOf(duration));
|
send(cmd, key, uuid, String.valueOf(duration));
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.wait();
|
lock.wait();
|
||||||
}
|
}
|
||||||
@ -599,7 +592,6 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
// ================================================== rpc ==================================================
|
// ================================================== rpc ==================================================
|
||||||
// -- 调用端 --
|
// -- 调用端 --
|
||||||
private static Map<String, Rpc> rpcMap = new ConcurrentHashMap<>();
|
private static Map<String, Rpc> rpcMap = new ConcurrentHashMap<>();
|
||||||
private static Map<String, TypeToken> rpcRetType = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Comment("rpc call")
|
@Comment("rpc call")
|
||||||
public RpcResult<Void> rpc(String topic, Object v) {
|
public RpcResult<Void> rpc(String topic, Object v) {
|
||||||
@ -613,14 +605,18 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
|
|
||||||
@Comment("rpc call")
|
@Comment("rpc call")
|
||||||
public <T, R> RpcResult<R> rpc(String topic, T v, TypeToken<R> typeToken, long timeout) {
|
public <T, R> RpcResult<R> rpc(String topic, T v, TypeToken<R> typeToken, long timeout) {
|
||||||
Rpc rpc = new Rpc<>(APP_NAME, Utility.uuid(), topic, v);
|
Rpc rpc = new Rpc<>(APP_NAME, topic, v);
|
||||||
|
rpc.setTypeToken(typeToken);
|
||||||
|
|
||||||
String ruk = rpc.getRuk();
|
String ruk = rpc.getRuk();
|
||||||
rpcMap.put(ruk, rpc);
|
rpcMap.put(ruk, rpc);
|
||||||
if (typeToken != null) {
|
|
||||||
rpcRetType.put(ruk, typeToken);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
publish(topic, rpc); // send("rpc", topic, toStr(rpc));
|
if (eventMap.containsKey(topic)) { // 本地调用
|
||||||
|
rpcCallQueue.add(Event.of(topic, rpc));
|
||||||
|
} else {
|
||||||
|
rpc.setValue(toStr(rpc.getValue()));
|
||||||
|
publish(topic, rpc); // send("rpc", topic, toStr(rpc));
|
||||||
|
}
|
||||||
synchronized (rpc) {
|
synchronized (rpc) {
|
||||||
if (timeout <= 0) {
|
if (timeout <= 0) {
|
||||||
timeout = 1000 * 15;
|
timeout = 1000 * 15;
|
||||||
@ -670,16 +666,38 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
|
|
||||||
// RpcResult: {ruk:xxx-xxxx, retcode:0}
|
// RpcResult: {ruk:xxx-xxxx, retcode:0}
|
||||||
@Comment("rpc call back consumer")
|
@Comment("rpc call back consumer")
|
||||||
private void rpcAccept(String value) {
|
private <T> void rpcAccept(T value) {
|
||||||
|
// 接收到 本地调用返回的 RpcResult
|
||||||
|
if (value instanceof RpcResult) {
|
||||||
|
String ruk = ((RpcResult) value).getRuk();
|
||||||
|
Rpc rpc = rpcMap.remove(ruk);
|
||||||
|
if (rpc == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 本地模式下返回的数据对象类型需要和处理端一致,不然会出现类型转换异常 - 解决办法,当出现不一致的情况取数据做转换
|
||||||
|
TypeToken typeToken = rpc.getTypeToken();
|
||||||
|
if (typeToken.getType() != ((RpcResult<?>) value).getResult().getClass()) {
|
||||||
|
Object result = convert.convertFrom(typeToken.getType(), toStr(((RpcResult<?>) value).getResult()));
|
||||||
|
((RpcResult<Object>) value).setResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc.setRpcResult((RpcResult) value);
|
||||||
|
synchronized (rpc) {
|
||||||
|
rpc.notify();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RpcResult resp = convert.convertFrom(new TypeToken<RpcResult<String>>() {
|
RpcResult resp = convert.convertFrom(new TypeToken<RpcResult<String>>() {
|
||||||
}.getType(), value);
|
}.getType(), (String) value);
|
||||||
|
|
||||||
String ruk = resp.getRuk();
|
String ruk = resp.getRuk();
|
||||||
Rpc rpc = rpcMap.remove(ruk);
|
Rpc rpc = rpcMap.remove(ruk);
|
||||||
if (rpc == null) {
|
if (rpc == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TypeToken typeToken = rpcRetType.get(ruk);
|
TypeToken typeToken = rpc.getTypeToken();
|
||||||
|
|
||||||
Object result = resp.getResult();
|
Object result = resp.getResult();
|
||||||
if (result != null && typeToken != null && !"java.lang.String".equals(typeToken.getType().getTypeName()) && !"java.lang.Void".equals(typeToken.getType().getTypeName())) {
|
if (result != null && typeToken != null && !"java.lang.String".equals(typeToken.getType().getTypeName()) && !"java.lang.Void".equals(typeToken.getType().getTypeName())) {
|
||||||
@ -703,18 +721,29 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
|
|
||||||
@Comment("rpc call consumer")
|
@Comment("rpc call consumer")
|
||||||
public <T, R> void rpcSubscribe(String topic, TypeToken<T> typeToken, Function<Rpc<T>, RpcResult<R>> fun) {
|
public <T, R> void rpcSubscribe(String topic, TypeToken<T> typeToken, Function<Rpc<T>, RpcResult<R>> fun) {
|
||||||
Consumer<String> consumer = v -> {
|
Consumer<T> consumer = v -> {
|
||||||
Rpc<T> rpc = null;
|
Rpc<T> rpc = null;
|
||||||
try {
|
try {
|
||||||
rpc = convert.convertFrom(new TypeToken<Rpc<String>>() {
|
if (v instanceof String) {
|
||||||
}.getType(), v);
|
rpc = convert.convertFrom(new TypeToken<Rpc<String>>() {
|
||||||
|
}.getType(), (String) v);
|
||||||
|
} else {
|
||||||
|
rpc = (Rpc<T>) v;
|
||||||
|
}
|
||||||
|
|
||||||
// 参数转换
|
// 参数转换
|
||||||
T paras = convert.convertFrom(typeToken.getType(), (String) rpc.getValue());
|
if (rpc.getValue() instanceof String && !"java.lang.String".equals(typeToken.getType().getTypeName())) {
|
||||||
rpc.setValue(paras);
|
T paras = convert.convertFrom(typeToken.getType(), (String) rpc.getValue());
|
||||||
|
rpc.setValue(paras);
|
||||||
|
}
|
||||||
|
|
||||||
RpcResult result = fun.apply(rpc);
|
RpcResult result = fun.apply(rpc);
|
||||||
result.setResult(toStr(result.getResult()));
|
if (APP_NAME.equals(rpc.getBackTopic())) {
|
||||||
publish(rpc.getBackTopic(), result);
|
rpcBackQueue.add(Event.of(topic, result));
|
||||||
|
} else {
|
||||||
|
result.setResult(toStr(result.getResult())); // 远程模式 结果转换
|
||||||
|
publish(rpc.getBackTopic(), result);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.WARNING, "rpc call consumer error: " + v, e);
|
logger.log(Level.WARNING, "rpc call consumer error: " + v, e);
|
||||||
publish(rpc.getBackTopic(), rpc.retError("服务调用失败!"));
|
publish(rpc.getBackTopic(), rpc.retError("服务调用失败!"));
|
||||||
@ -723,6 +752,6 @@ public class ZHubClient extends AbstractConsumer implements IConsumer, IProducer
|
|||||||
};
|
};
|
||||||
|
|
||||||
rpcTopics.add(topic);
|
rpcTopics.add(topic);
|
||||||
subscribe(topic, consumer);
|
subscribe(topic, typeToken, consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package net.tccn.timer;
|
package dev.zhub.timer;
|
||||||
|
|
||||||
import net.tccn.timer.queue.TimerQueue;
|
import dev.zhub.timer.queue.TimerQueue;
|
||||||
import net.tccn.timer.task.Task;
|
import dev.zhub.timer.task.Task;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
@ -24,7 +24,7 @@ public class TimerExecutor {
|
|||||||
for (Task t : task) {
|
for (Task t : task) {
|
||||||
t.setTimerExecutor(this);
|
t.setTimerExecutor(this);
|
||||||
queue.push(t);
|
queue.push(t);
|
||||||
logger.finest("add new task : " + t.getName());
|
// logger.finest("add new task : " + t.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
package net.tccn.timer;
|
package dev.zhub.timer;
|
||||||
|
|
||||||
import net.tccn.timer.scheduled.Scheduled;
|
import dev.zhub.timer.scheduled.Scheduled;
|
||||||
import net.tccn.timer.task.Job;
|
import dev.zhub.timer.task.Job;
|
||||||
import net.tccn.timer.task.Task;
|
import dev.zhub.timer.task.Task;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
@ -93,10 +93,10 @@ public class TimerTask implements Task {
|
|||||||
if (!isComplete) {
|
if (!isComplete) {
|
||||||
int count = execCount.incrementAndGet(); // 执行次数+1
|
int count = execCount.incrementAndGet(); // 执行次数+1
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
// long start = System.currentTimeMillis();
|
||||||
job.execute(this);
|
job.execute(this);
|
||||||
long end = System.currentTimeMillis();
|
// long end = System.currentTimeMillis();
|
||||||
logger.finest(String.format("task [%s] : not complete -> %s, time: %s ms, exec count: %s.", getName(), isComplete ? "had complete" : "not complete", end - start, count));
|
// logger.finest(String.format("task [%s] : not complete -> %s, time: %s ms, exec count: %s.", getName(), isComplete ? "had complete" : "not complete", end - start, count));
|
||||||
|
|
||||||
if (!isComplete) {
|
if (!isComplete) {
|
||||||
timerExecutor.add(this, true);
|
timerExecutor.add(this, true);
|
@ -1,6 +1,6 @@
|
|||||||
package net.tccn.timer;
|
package dev.zhub.timer;
|
||||||
|
|
||||||
import net.tccn.timer.scheduled.ScheduledCycle;
|
import dev.zhub.timer.scheduled.ScheduledCycle;
|
||||||
import org.redkale.util.Utility;
|
import org.redkale.util.Utility;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
@ -1,6 +1,6 @@
|
|||||||
package net.tccn.timer.queue;
|
package dev.zhub.timer.queue;
|
||||||
|
|
||||||
import net.tccn.timer.task.Task;
|
import dev.zhub.timer.task.Task;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn.timer.scheduled;
|
package dev.zhub.timer.scheduled;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn.timer.scheduled;
|
package dev.zhub.timer.scheduled;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn.timer.scheduled;
|
package dev.zhub.timer.scheduled;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
@ -1,4 +1,4 @@
|
|||||||
package net.tccn.timer.task;
|
package dev.zhub.timer.task;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author: liangxianyou at 2018/12/8 17:24.
|
* @author: liangxianyou at 2018/12/8 17:24.
|
@ -1,7 +1,7 @@
|
|||||||
package net.tccn.timer.task;
|
package dev.zhub.timer.task;
|
||||||
|
|
||||||
import net.tccn.timer.TimerExecutor;
|
import dev.zhub.timer.TimerExecutor;
|
||||||
import net.tccn.timer.scheduled.Scheduled;
|
import dev.zhub.timer.scheduled.Scheduled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author: liangxianyou at 2018/8/5 19:32.
|
* @author: liangxianyou at 2018/8/5 19:32.
|
@ -8,16 +8,26 @@ import org.redkale.annotation.Resource;
|
|||||||
import org.redkale.convert.Convert;
|
import org.redkale.convert.Convert;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
import org.redkale.source.AbstractCacheSource;
|
import org.redkale.source.AbstractCacheSource;
|
||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.*;
|
||||||
import org.redkale.util.RedkaleClassLoader;
|
|
||||||
import org.redkale.util.RedkaleException;
|
|
||||||
import org.redkale.util.ResourceFactory;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static org.redkale.boot.Application.RESNAME_APP_EXECUTOR;
|
||||||
|
import static org.redkale.boot.Application.RESNAME_APP_NAME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
|
*
|
||||||
* @since 2.8.0
|
* @since 2.8.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractRedisSource extends AbstractCacheSource {
|
public abstract class AbstractRedisSource extends AbstractCacheSource {
|
||||||
@ -26,27 +36,39 @@ public abstract class AbstractRedisSource extends AbstractCacheSource {
|
|||||||
|
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
|
@Resource(name = RESNAME_APP_NAME, required = false)
|
||||||
|
protected String appName = "";
|
||||||
|
|
||||||
@Resource(required = false)
|
@Resource(required = false)
|
||||||
protected ResourceFactory resourceFactory;
|
protected ResourceFactory resourceFactory;
|
||||||
|
|
||||||
@Resource(required = false)
|
@Resource(required = false)
|
||||||
protected JsonConvert defaultConvert;
|
protected JsonConvert defaultConvert;
|
||||||
|
|
||||||
@Resource(name = "$_convert", required = false)
|
@Resource(name = Resource.PARENT_NAME + "_convert", required = false)
|
||||||
protected JsonConvert convert;
|
protected JsonConvert convert;
|
||||||
|
|
||||||
protected int db;
|
protected int db;
|
||||||
|
|
||||||
protected RedisCryptor cryptor;
|
protected RedisCryptor cryptor;
|
||||||
|
|
||||||
protected AnyValue config;
|
protected AnyValue conf;
|
||||||
|
|
||||||
|
private ExecutorService subExecutor;
|
||||||
|
|
||||||
|
private final ReentrantLock subExecutorLock = new ReentrantLock();
|
||||||
|
|
||||||
|
@Resource(name = RESNAME_APP_EXECUTOR, required = false)
|
||||||
|
protected ExecutorService workExecutor;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(AnyValue conf) {
|
public void init(AnyValue conf) {
|
||||||
this.config = conf;
|
this.conf = conf;
|
||||||
super.init(conf);
|
super.init(conf);
|
||||||
this.name = conf.getValue("name", "");
|
this.name = conf.getValue("name", "");
|
||||||
if (this.convert == null) this.convert = this.defaultConvert;
|
if (this.convert == null) {
|
||||||
|
this.convert = this.defaultConvert;
|
||||||
|
}
|
||||||
if (conf != null) {
|
if (conf != null) {
|
||||||
String cryptStr = conf.getValue(CACHE_SOURCE_CRYPTOR, "").trim();
|
String cryptStr = conf.getValue(CACHE_SOURCE_CRYPTOR, "").trim();
|
||||||
if (!cryptStr.isEmpty()) {
|
if (!cryptStr.isEmpty()) {
|
||||||
@ -75,6 +97,46 @@ public abstract class AbstractRedisSource extends AbstractCacheSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean acceptsConf(AnyValue config) {
|
||||||
|
if (config == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return "redis".equalsIgnoreCase(config.getValue(CACHE_SOURCE_TYPE))
|
||||||
|
|| getClass().getName().equalsIgnoreCase(config.getValue(CACHE_SOURCE_TYPE))
|
||||||
|
|| config.getValue(CACHE_SOURCE_NODES, config.getValue("url", "")).startsWith("redis://")
|
||||||
|
|| config.getValue(CACHE_SOURCE_NODES, config.getValue("url", "")).startsWith("rediss://");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ExecutorService subExecutor() {
|
||||||
|
ExecutorService executor = subExecutor;
|
||||||
|
if (executor != null) {
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
subExecutorLock.lock();
|
||||||
|
try {
|
||||||
|
if (subExecutor == null) {
|
||||||
|
String threadNameFormat = "CacheSource-" + resourceName() + "-SubThread-%s";
|
||||||
|
Function<String, ExecutorService> func = Utility.virtualExecutorFunction();
|
||||||
|
final AtomicInteger counter = new AtomicInteger();
|
||||||
|
subExecutor = func == null ? Executors.newFixedThreadPool(Utility.cpus(), r -> {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setDaemon(true);
|
||||||
|
int c = counter.incrementAndGet();
|
||||||
|
t.setName(String.format(threadNameFormat, "Virtual-" + (c < 10 ? ("00" + c) : (c < 100 ? ("0" + c) : c))));
|
||||||
|
return t;
|
||||||
|
}) : func.apply(threadNameFormat);
|
||||||
|
}
|
||||||
|
executor = subExecutor;
|
||||||
|
} finally {
|
||||||
|
subExecutorLock.unlock();
|
||||||
|
}
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getNodes(AnyValue config) {
|
||||||
|
return config.getValue(CACHE_SOURCE_NODES, config.getValue("url", ""));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception { //在 Application 关闭时调用
|
public void close() throws Exception { //在 Application 关闭时调用
|
||||||
destroy(null);
|
destroy(null);
|
||||||
@ -94,12 +156,22 @@ public abstract class AbstractRedisSource extends AbstractCacheSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected <T> T decryptValue(String key, RedisCryptor cryptor, Convert c, Type type, byte[] bs) {
|
protected <T> T decryptValue(String key, RedisCryptor cryptor, Convert c, Type type, byte[] bs) {
|
||||||
if (bs == null) return null;
|
if (bs == null) {
|
||||||
if (type == byte[].class) return (T) bs;
|
return null;
|
||||||
|
}
|
||||||
|
if (type == byte[].class) {
|
||||||
|
return (T) bs;
|
||||||
|
}
|
||||||
|
if (cryptor == null && type == String.class) {
|
||||||
|
return (T) new String(bs, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
if (cryptor == null || (type instanceof Class && (((Class) type).isPrimitive() || Number.class.isAssignableFrom((Class) type)))) {
|
if (cryptor == null || (type instanceof Class && (((Class) type).isPrimitive() || Number.class.isAssignableFrom((Class) type)))) {
|
||||||
return (T) (c == null ? this.convert : c).convertFrom(type, bs);
|
return (T) (c == null ? this.convert : c).convertFrom(type, bs);
|
||||||
}
|
}
|
||||||
String deval = cryptor.decrypt(key, new String(bs, StandardCharsets.UTF_8));
|
String deval = cryptor.decrypt(key, new String(bs, StandardCharsets.UTF_8));
|
||||||
|
if (type == String.class) {
|
||||||
|
return (T) deval;
|
||||||
|
}
|
||||||
return deval == null ? null : (T) (c == null ? this.convert : c).convertFrom(type, deval.getBytes(StandardCharsets.UTF_8));
|
return deval == null ? null : (T) (c == null ? this.convert : c).convertFrom(type, deval.getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,20 +184,51 @@ public abstract class AbstractRedisSource extends AbstractCacheSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected <T> byte[] encryptValue(String key, RedisCryptor cryptor, Type type, Convert c, T value) {
|
protected <T> byte[] encryptValue(String key, RedisCryptor cryptor, Type type, Convert c, T value) {
|
||||||
if (value == null) return null;
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Type t = type == null ? value.getClass() : type;
|
Type t = type == null ? value.getClass() : type;
|
||||||
if (cryptor == null && type == String.class) {
|
if (cryptor == null && t == String.class) {
|
||||||
return value.toString().getBytes(StandardCharsets.UTF_8);
|
return value.toString().getBytes(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
return encryptValue(key, cryptor, t, (c == null ? this.convert : c).convertToBytes(t, value));
|
byte[] bs = (c == null ? this.convert : c).convertToBytes(t, value);
|
||||||
|
if (bs.length > 1 && t instanceof Class && !CharSequence.class.isAssignableFrom((Class) t)) {
|
||||||
|
if (bs[0] == '"' && bs[bs.length - 1] == '"') {
|
||||||
|
bs = Arrays.copyOfRange(bs, 1, bs.length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return encryptValue(key, cryptor, t, bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] encryptValue(String key, RedisCryptor cryptor, Type type, byte[] bs) {
|
protected byte[] encryptValue(String key, RedisCryptor cryptor, Type type, byte[] bs) {
|
||||||
if (bs == null) return null;
|
if (bs == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (cryptor == null || (type instanceof Class && (((Class) type).isPrimitive() || Number.class.isAssignableFrom((Class) type)))) {
|
if (cryptor == null || (type instanceof Class && (((Class) type).isPrimitive() || Number.class.isAssignableFrom((Class) type)))) {
|
||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
String enval = cryptor.encrypt(key, new String(bs, StandardCharsets.UTF_8));
|
String enval = cryptor.encrypt(key, new String(bs, StandardCharsets.UTF_8));
|
||||||
return enval == null ? null : enval.getBytes(StandardCharsets.UTF_8);
|
return enval == null ? null : enval.getBytes(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected <T extends Number> T decryptScore(Class<T> scoreType, Double score) {
|
||||||
|
if (score == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (scoreType == int.class || scoreType == Integer.class) {
|
||||||
|
return (T) (Number) score.intValue();
|
||||||
|
} else if (scoreType == long.class || scoreType == Long.class) {
|
||||||
|
return (T) (Number) score.longValue();
|
||||||
|
} else if (scoreType == float.class || scoreType == Float.class) {
|
||||||
|
return (T) (Number) score.floatValue();
|
||||||
|
} else if (scoreType == double.class || scoreType == Double.class) {
|
||||||
|
return (T) (Number) score;
|
||||||
|
} else {
|
||||||
|
return JsonConvert.root().convertFrom(scoreType, score.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CompletableFuture<Integer> returnFutureSize(List<CompletableFuture<Void>> futures) {
|
||||||
|
return futures == null || futures.isEmpty() ? CompletableFuture.completedFuture(0) : Utility.allOfFutures(futures).thenApply(v -> futures.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,6 +145,8 @@ public class MyRedisCacheSource extends RedisCacheSource {
|
|||||||
* */
|
* */
|
||||||
|
|
||||||
// --------------------
|
// --------------------
|
||||||
|
/*
|
||||||
|
supper had support
|
||||||
public <N extends Number> void zadd(String key, Map<Serializable, N> kv) {
|
public <N extends Number> void zadd(String key, Map<Serializable, N> kv) {
|
||||||
if (kv == null || kv.isEmpty()) {
|
if (kv == null || kv.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@ -155,16 +157,17 @@ public class MyRedisCacheSource extends RedisCacheSource {
|
|||||||
args.add(v);
|
args.add(v);
|
||||||
});
|
});
|
||||||
|
|
||||||
sendAsync("ZADD", key, args.toArray(Serializable[]::new)).join();
|
sendAsync(RedisCommand.ZADD, key, args.toArray(Serializable[]::new)).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <N extends Number> double zincr(String key, Serializable number, N n) {
|
public <N extends Number> double zincr(String key, Serializable number, N n) {
|
||||||
return sendAsync("ZINCRBY", key, number, n).thenApply(x -> x.getDoubleValue(0d)).join();
|
return sendAsync(RedisCommand.ZINCRBY, key, number, n).thenApply(x -> x.getDoubleValue(0d)).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void zrem(String key, Serializable... vs) {
|
@Override
|
||||||
sendAsync("ZREM", key, vs).join();
|
public long zrem(String key, String... vs) {
|
||||||
}
|
return sendAsync(RedisCommand.ZREM, key, keysArgs(key, vs)).thenApply(x -> x.getLongValue(0L)).join();
|
||||||
|
}*/
|
||||||
|
|
||||||
/*public <T> List<T> zexists(String key, T... fields) {
|
/*public <T> List<T> zexists(String key, T... fields) {
|
||||||
if (fields == null || fields.length == 0) {
|
if (fields == null || fields.length == 0) {
|
||||||
@ -196,27 +199,27 @@ public class MyRedisCacheSource extends RedisCacheSource {
|
|||||||
|
|
||||||
//--------------------- bit ------------------------------
|
//--------------------- bit ------------------------------
|
||||||
public boolean getBit(String key, int offset) {
|
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();
|
return sendAsync(RedisCommand.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) {
|
public void setBit(String key, int offset, boolean bool) {
|
||||||
sendAsync("SETBIT", key, offset, bool ? 1 : 0).join();
|
sendAsync(RedisCommand.SETBIT, key, keysArgs(key, offset + "", bool ? "1" : "0")).join();
|
||||||
}
|
}
|
||||||
//--------------------- bit ------------------------------
|
//--------------------- bit ------------------------------
|
||||||
|
|
||||||
//--------------------- lock ------------------------------
|
//--------------------- lock ------------------------------
|
||||||
// 尝试加锁,成功返回0,否则返回上一锁剩余毫秒值
|
// 尝试加锁,成功返回0,否则返回上一锁剩余毫秒值
|
||||||
public long tryLock(String key, int millis) {
|
public long tryLock(String key, int millis) {
|
||||||
Serializable[] obj = {"" +
|
String[] obj = {"" +
|
||||||
"if (redis.call('EXISTS',KEYS[1]) == 0) then " +
|
"if (redis.call('EXISTS',KEYS[1]) == 0) then " +
|
||||||
"redis.call('PSETEX',KEYS[1],ARGV[1],1); " +
|
"redis.call('PSETEX',KEYS[1],ARGV[1],1); " +
|
||||||
"return 0; " +
|
"return 0; " +
|
||||||
"else " +
|
"else " +
|
||||||
"return redis.call('PTTL',KEYS[1]); " +
|
"return redis.call('PTTL',KEYS[1]); " +
|
||||||
"end;", 1, key, millis
|
"end;", 1 + "", key, millis + ""
|
||||||
};
|
};
|
||||||
|
|
||||||
return sendAsync("EVAL", null, obj).thenApply(v -> v.getIntValue(1)).join();
|
return sendAsync(RedisCommand.EVAL, null, keysArgs(null, obj)).thenApply(v -> v.getIntValue(1)).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加锁
|
// 加锁
|
||||||
@ -244,29 +247,33 @@ public class MyRedisCacheSource extends RedisCacheSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void set(String key, Serializable value) {
|
public void set(String key, Serializable value) {
|
||||||
sendAsync("SET", key, value).join();
|
sendAsync(RedisCommand.SET, key, keysArgs(key, value + "")).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------- set ------------------------------
|
//--------------------- set ------------------------------
|
||||||
public <T> void sadd(String key, Collection<T> args) {
|
/*public <T> void sadd(String key, Collection<T> args) {
|
||||||
saddAsync(key, args.toArray(Serializable[]::new)).join();
|
saddAsync(key, args.toArray(T[]::new)).join();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*public void sadd(String key, Serializable... args) {
|
||||||
|
String[] arr = new String[args.length];
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
arr[i] = args[i] + "";
|
||||||
|
}
|
||||||
|
saddAsync(key, arr).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sadd(String key, Serializable... args) {
|
public void srem(String key, String... args) {
|
||||||
saddAsync(key, Arrays.stream(args).toArray(Serializable[]::new)).join();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void srem(String key, Serializable... args) {
|
|
||||||
sremAsync(key, args).join();
|
sremAsync(key, args).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<RedisCacheResult> saddAsync(String key, Serializable... args) {
|
public CompletableFuture<RedisCacheResult> saddAsync(String key, Serializable... args) {
|
||||||
return sendAsync("SADD", key, args);
|
return sendAsync(RedisCommand.SADD, key, keysArgs(key, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<RedisCacheResult> sremAsync(String key, Serializable... args) {
|
public CompletableFuture<RedisCacheResult> sremAsync(String key, String... args) {
|
||||||
return sendAsync("SREM", key, args);
|
return sendAsync(RedisCommand.SREM, key, keysArgs(key, args));
|
||||||
}
|
}*/
|
||||||
|
|
||||||
//--------------------- hm ------------------------------
|
//--------------------- hm ------------------------------
|
||||||
|
|
||||||
@ -286,14 +293,14 @@ public class MyRedisCacheSource extends RedisCacheSource {
|
|||||||
setHmsAsync(key, kv).join();
|
setHmsAsync(key, kv).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<RedisCacheResult> setHmsAsync(String key, Map<Serializable, Serializable> kv) {
|
public CompletableFuture<RedisCacheResult> setHmsAsync(String key, Map<String, Serializable> kv) {
|
||||||
List<Serializable> args = new ArrayList();
|
List<String> args = new ArrayList();
|
||||||
kv.forEach((k, v) -> {
|
kv.forEach((k, v) -> {
|
||||||
args.add(k);
|
args.add(k);
|
||||||
args.add(v);
|
args.add(v + "");
|
||||||
});
|
});
|
||||||
|
|
||||||
return sendAsync("HMSET", key, args.toArray(Serializable[]::new));
|
return sendAsync(RedisCommand.HMSET, key, keysArgs(key, args.toArray(String[]::new)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHm(String key, String field) {
|
public String getHm(String key, String field) {
|
||||||
|
@ -8,32 +8,35 @@ import org.redkale.util.Utility;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCRC16 {
|
public class RedisCRC16 {
|
||||||
|
|
||||||
|
private static final int MAX_SLOT = 16384;
|
||||||
|
|
||||||
private static final int[] LOOKUP_TABLE = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6,
|
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,
|
0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273,
|
||||||
0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF,
|
0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF,
|
||||||
0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528,
|
0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528,
|
||||||
0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695,
|
0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695,
|
||||||
0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886,
|
0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886,
|
||||||
0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A,
|
0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A,
|
||||||
0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF,
|
0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF,
|
||||||
0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60,
|
0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60,
|
||||||
0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5,
|
0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5,
|
||||||
0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59,
|
0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59,
|
||||||
0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2,
|
0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2,
|
||||||
0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F,
|
0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F,
|
||||||
0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8,
|
0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8,
|
||||||
0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424,
|
0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424,
|
||||||
0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691,
|
0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691,
|
||||||
0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A,
|
0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A,
|
||||||
0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F,
|
0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F,
|
||||||
0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3,
|
0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3,
|
||||||
0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64,
|
0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64,
|
||||||
0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9,
|
0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9,
|
||||||
0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
|
0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
|
||||||
|
|
||||||
private RedisCRC16() {
|
private RedisCRC16() {
|
||||||
}
|
}
|
||||||
@ -46,7 +49,7 @@ public class RedisCRC16 {
|
|||||||
return crc & 0xFFFF;
|
return crc & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int calcSlot(int maxSlot, byte[] key) {
|
public static int calcSlot(byte[] key) {
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -57,11 +60,10 @@ public class RedisCRC16 {
|
|||||||
key = Arrays.copyOfRange(key, start + 1, end);
|
key = Arrays.copyOfRange(key, start + 1, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int result = crc16(key) % maxSlot;
|
return crc16(key) % MAX_SLOT;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int calcSlot(int maxSlot, String key) {
|
public static int calcSlot(String key) {
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -72,7 +74,6 @@ public class RedisCRC16 {
|
|||||||
key = key.substring(start + 1, end);
|
key = key.substring(start + 1, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int result = crc16(key.getBytes()) % maxSlot;
|
return crc16(key.getBytes()) % MAX_SLOT;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,23 +9,45 @@ import org.redkale.net.AsyncConnection;
|
|||||||
import org.redkale.net.AsyncGroup;
|
import org.redkale.net.AsyncGroup;
|
||||||
import org.redkale.net.client.Client;
|
import org.redkale.net.client.Client;
|
||||||
import org.redkale.net.client.ClientAddress;
|
import org.redkale.net.client.ClientAddress;
|
||||||
|
import org.redkale.util.Traces;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCacheClient extends Client<RedisCacheConnection, RedisCacheRequest, RedisCacheResult> {
|
public class RedisCacheClient extends Client<RedisCacheConnection, RedisCacheRequest, RedisCacheResult> {
|
||||||
|
|
||||||
public RedisCacheClient(String name, AsyncGroup group, String key, ClientAddress address, int maxConns, int maxPipelines, RedisCacheReqAuth authReq, RedisCacheReqDB dbReq) {
|
public RedisCacheClient(String appName, 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
|
super(name, group, true, address, maxConns, maxPipelines, () -> new RedisCacheReqPing(), () -> new RedisCacheReqClose(), null); //maxConns
|
||||||
if (authReq != null || dbReq != null) {
|
RedisCacheReqClientName clientNameReq = new RedisCacheReqClientName(appName, name);
|
||||||
if (authReq != null && dbReq != null) {
|
if (authReq != null && dbReq != null) {
|
||||||
this.authenticate = conn -> writeChannel(conn, authReq).thenCompose(v -> writeChannel(conn, dbReq)).thenApply(v -> conn);
|
this.authenticate = traceid -> {
|
||||||
} else if (authReq != null) {
|
Traces.currentTraceid(traceid);
|
||||||
this.authenticate = conn -> writeChannel(conn, authReq).thenApply(v -> conn);
|
return conn -> writeChannelBatch(conn, authReq.createTime(), dbReq.createTime(), clientNameReq.createTime())
|
||||||
} else {
|
.thenApply(v -> conn);
|
||||||
this.authenticate = conn -> writeChannel(conn, dbReq).thenApply(v -> conn);
|
};
|
||||||
}
|
} else if (authReq != null) {
|
||||||
|
this.authenticate = traceid -> {
|
||||||
|
Traces.currentTraceid(traceid);
|
||||||
|
return conn -> writeChannelBatch(conn, authReq.createTime(), clientNameReq.createTime())
|
||||||
|
.thenApply(v -> conn);
|
||||||
|
};
|
||||||
|
} else if (dbReq != null) {
|
||||||
|
this.authenticate = traceid -> {
|
||||||
|
Traces.currentTraceid(traceid);
|
||||||
|
return conn -> writeChannelBatch(conn, dbReq.createTime(), clientNameReq.createTime())
|
||||||
|
.thenApply(v -> conn);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.authenticate = traceid -> {
|
||||||
|
Traces.currentTraceid(traceid);
|
||||||
|
return conn -> writeChannel(conn, clientNameReq.createTime())
|
||||||
|
.thenApply(v -> conn);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
this.readTimeoutSeconds = 3;
|
||||||
|
this.writeTimeoutSeconds = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -8,6 +8,7 @@ package org.redkalex.cache.redis;
|
|||||||
import org.redkale.net.client.ClientCodec;
|
import org.redkale.net.client.ClientCodec;
|
||||||
import org.redkale.net.client.ClientConnection;
|
import org.redkale.net.client.ClientConnection;
|
||||||
import org.redkale.util.ByteArray;
|
import org.redkale.util.ByteArray;
|
||||||
|
import org.redkale.util.RedkaleException;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@ -16,39 +17,42 @@ import java.util.List;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCacheCodec extends ClientCodec<RedisCacheRequest, RedisCacheResult> {
|
public class RedisCacheCodec extends ClientCodec<RedisCacheRequest, RedisCacheResult> {
|
||||||
|
|
||||||
protected static final byte TYPE_STRING = '+'; //简单字符串(不包含CRLF)类型
|
protected static final byte TYPE_BULK = '$'; //字符串块类型, 例如:$6\r\n\abcdef\r\n,NULL字符串:$-1\r\n
|
||||||
|
|
||||||
protected static final byte TYPE_ERROR = '-'; //错误(不包含CRLF)类型
|
protected static final byte TYPE_MULTI = '*'; //数组,紧接的数字为数组长度
|
||||||
|
|
||||||
protected static final byte TYPE_NUMBER = ':'; //整型
|
protected static final byte TYPE_STRING = '+'; //字符串值类型,字符串以\r\n结尾, 例如:+OK\r\n
|
||||||
|
|
||||||
protected static final byte TYPE_BULK = '$'; //块字符串
|
protected static final byte TYPE_ERROR = '-'; //错误字符串类型,字符串以\r\n结尾, 例如:-ERR unknown command 'red'\r\n
|
||||||
|
|
||||||
protected static final byte TYPE_ARRAY = '*'; //数组
|
protected static final byte TYPE_NUMBER = ':'; //整型, 例如::2\r\n
|
||||||
|
|
||||||
protected static final Logger logger = Logger.getLogger(RedisCacheCodec.class.getSimpleName());
|
private static final Logger logger = Logger.getLogger(RedisCacheCodec.class.getSimpleName());
|
||||||
|
|
||||||
protected byte halfFrameCmd;
|
private ByteArray halfFrameBytes;
|
||||||
|
|
||||||
protected int halfFrameBulkLength = -10;
|
private int halfFrameBulkLength = Integer.MIN_VALUE;
|
||||||
|
|
||||||
protected int halfFrameArraySize = -10;
|
private int halfFrameMultiSize = Integer.MIN_VALUE;
|
||||||
|
|
||||||
protected int halfFrameArrayIndex; //从0开始
|
private int halfFrameMultiItemIndex; //从0开始
|
||||||
|
|
||||||
protected int halfFrameArrayItemLength = -10;
|
private byte halfFrameMultiItemType;
|
||||||
|
|
||||||
protected ByteArray halfFrameBytes;
|
private int halfFrameMultiItemLength = Integer.MIN_VALUE;
|
||||||
|
|
||||||
protected byte frameType;
|
private byte frameType;
|
||||||
|
|
||||||
protected byte[] frameValue; //(不包含CRLF)
|
private byte[] frameCursor;
|
||||||
|
|
||||||
protected List<byte[]> frameList; //(不包含CRLF)
|
private byte[] frameValue;
|
||||||
|
|
||||||
|
private List<byte[]> frameList;
|
||||||
|
|
||||||
private ByteArray recyclableArray;
|
private ByteArray recyclableArray;
|
||||||
|
|
||||||
@ -56,148 +60,142 @@ public class RedisCacheCodec extends ClientCodec<RedisCacheRequest, RedisCacheRe
|
|||||||
super(connection);
|
super(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ByteArray pollArray(ByteArray array) {
|
private ByteArray pollArray(ByteArray array) {
|
||||||
if (recyclableArray == null) {
|
if (recyclableArray == null) {
|
||||||
recyclableArray = new ByteArray();
|
recyclableArray = new ByteArray();
|
||||||
} else {
|
|
||||||
recyclableArray.clear();
|
|
||||||
}
|
}
|
||||||
recyclableArray.clear();
|
recyclableArray.clear();
|
||||||
if (array != null) {
|
if (array != null) {
|
||||||
recyclableArray.put(array, 0, array.length());
|
recyclableArray.put(array);
|
||||||
}
|
}
|
||||||
return recyclableArray;
|
return recyclableArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkBytesFrame(RedisCacheConnection conn, ByteBuffer buffer, ByteArray array) {
|
private boolean readFrames(RedisCacheConnection conn, ByteBuffer buffer, ByteArray array) {
|
||||||
// byte[] dbs = new byte[buffer.remaining()];
|
// byte[] dbs = new byte[buffer.remaining()];
|
||||||
// for (int i = 0; i < dbs.length; i++) {
|
// for (int i = 0; i < dbs.length; i++) {
|
||||||
// dbs[i] = buffer.get(buffer.position() + i);
|
// dbs[i] = buffer.get(buffer.position() + i);
|
||||||
// }
|
// }
|
||||||
// ArrayDeque<ClientFuture> deque = (ArrayDeque) responseQueue(conn);
|
// (System. out).println("[" + Utility.nowMillis() + "] [" + Thread.currentThread().getName() + "]: " + conn + ", 原始数据: " + new String(dbs).replace("\r\n", " "));
|
||||||
// logger.log(Level.FINEST, "[" + Utility.nowMillis() + "] [" + Thread.currentThread().getName() + "]: " + conn + ", 原始数据: " + new String(dbs).replace("\r\n", " ") + ", req=" + deque.getFirst().getRequest());
|
|
||||||
|
|
||||||
array.clear();
|
array.clear();
|
||||||
byte type = halfFrameCmd == 0 ? buffer.get() : halfFrameCmd;
|
if (this.frameType == 0) {
|
||||||
if (halfFrameBytes != null) {
|
this.frameType = buffer.get();
|
||||||
array.put(halfFrameBytes, 0, halfFrameBytes.length());
|
} else if (halfFrameBytes != null) {
|
||||||
|
array.put(halfFrameBytes);
|
||||||
|
halfFrameBytes = null;
|
||||||
}
|
}
|
||||||
frameType = type;
|
if (frameType == TYPE_STRING || frameType == TYPE_ERROR || frameType == TYPE_NUMBER) {
|
||||||
if (type == TYPE_STRING || type == TYPE_ERROR || type == TYPE_NUMBER) {
|
if (!readComplete(buffer, array)) {
|
||||||
if (readComplete(buffer, array)) {
|
|
||||||
frameValue = array.getBytes();
|
|
||||||
} else {
|
|
||||||
halfFrameCmd = type;
|
|
||||||
halfFrameBytes = pollArray(array);
|
halfFrameBytes = pollArray(array);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (type == TYPE_BULK) {
|
frameValue = array.getBytes();
|
||||||
int bulkLength = halfFrameBulkLength;
|
} else if (frameType == TYPE_BULK) {
|
||||||
if (bulkLength < -2) {
|
if (halfFrameBulkLength == Integer.MIN_VALUE) {
|
||||||
if (!readComplete(buffer, array)) { //没有读到bulkLength
|
if (!readComplete(buffer, array)) { //没有读到bulkLength
|
||||||
halfFrameCmd = type;
|
|
||||||
halfFrameBulkLength = -10;
|
|
||||||
halfFrameBytes = pollArray(array);
|
halfFrameBytes = pollArray(array);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bulkLength = Integer.parseInt(array.toString(StandardCharsets.UTF_8));
|
halfFrameBulkLength = readInt(array);
|
||||||
array.clear();
|
array.clear();
|
||||||
}
|
}
|
||||||
if (bulkLength == -1) {
|
if (halfFrameBulkLength == -1) {
|
||||||
frameValue = null;
|
frameValue = null;
|
||||||
} else if (readComplete(buffer, array)) {
|
|
||||||
frameValue = array.getBytes();
|
|
||||||
} else {
|
} else {
|
||||||
halfFrameCmd = type;
|
int expect = halfFrameBulkLength + 2 - array.length();
|
||||||
halfFrameBulkLength = bulkLength;
|
if (buffer.remaining() < expect) {
|
||||||
halfFrameBytes = pollArray(array);
|
array.put(buffer);
|
||||||
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);
|
halfFrameBytes = pollArray(array);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
arraySize = Integer.parseInt(array.toString(StandardCharsets.UTF_8));
|
array.put(buffer, expect);
|
||||||
array.clear();
|
array.removeLastByte(); //移除\n
|
||||||
|
array.removeLastByte(); //移除\r
|
||||||
|
frameValue = array.getBytes();
|
||||||
}
|
}
|
||||||
int arrayIndex = halfFrameArrayIndex;
|
} else if (frameType == TYPE_MULTI) {
|
||||||
for (int i = arrayIndex; i < arraySize; i++) {
|
int size = halfFrameMultiSize;
|
||||||
int itemLength = halfFrameArrayItemLength;
|
if (size == Integer.MIN_VALUE) {
|
||||||
halfFrameArrayItemLength = -10;
|
if (!readComplete(buffer, array)) { //没有读到bulkLength
|
||||||
if (itemLength < -2) {
|
halfFrameBytes = pollArray(array);
|
||||||
if (!readComplete(buffer, array)) { //没有读到bulkLength
|
return false;
|
||||||
halfFrameCmd = type;
|
}
|
||||||
halfFrameArraySize = arraySize;
|
size = readInt(array);
|
||||||
halfFrameArrayIndex = i;
|
halfFrameMultiSize = size;
|
||||||
halfFrameArrayItemLength = -10;
|
array.clear();
|
||||||
halfFrameBytes = pollArray(array);
|
frameValue = null;
|
||||||
|
}
|
||||||
|
if (frameList == null) {
|
||||||
|
frameList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (size > 0) {
|
||||||
|
int index = halfFrameMultiItemIndex;
|
||||||
|
for (int i = index; i < size; i++) {
|
||||||
|
if (!buffer.hasRemaining()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
byte sign = array.get(0);
|
if (halfFrameMultiItemType == 0) {
|
||||||
itemLength = Integer.parseInt(array.toString(1, StandardCharsets.UTF_8));
|
halfFrameMultiItemType = buffer.get();
|
||||||
array.clear();
|
}
|
||||||
if (sign == TYPE_ARRAY) { //数组中嵌套数组,目前有 HSCAN
|
halfFrameMultiItemIndex = i;
|
||||||
frameValue = null;
|
final byte itemType = halfFrameMultiItemType;
|
||||||
if (frameList != null) {
|
if (itemType == TYPE_STRING || itemType == TYPE_ERROR || itemType == TYPE_NUMBER) {
|
||||||
frameList.clear();
|
if (!readComplete(buffer, array)) {
|
||||||
}
|
halfFrameBytes = pollArray(array);
|
||||||
clearHalfFrame();
|
|
||||||
if (itemLength == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
halfFrameCmd = sign;
|
|
||||||
halfFrameArraySize = itemLength;
|
|
||||||
if (!buffer.hasRemaining()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return checkBytesFrame(conn, buffer, array);
|
frameList.add(array.getBytes());
|
||||||
|
} else if (itemType == TYPE_BULK) {
|
||||||
|
if (halfFrameMultiItemLength == Integer.MIN_VALUE) {
|
||||||
|
if (!readComplete(buffer, array)) { //没有读到bulkLength
|
||||||
|
halfFrameBytes = pollArray(array);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
halfFrameMultiItemLength = readInt(array);
|
||||||
|
array.clear();
|
||||||
|
}
|
||||||
|
if (halfFrameMultiItemLength == -1) {
|
||||||
|
frameList.add(null);
|
||||||
|
} else {
|
||||||
|
int expect = halfFrameMultiItemLength + 2 - array.length();
|
||||||
|
if (buffer.remaining() < expect) {
|
||||||
|
array.put(buffer);
|
||||||
|
halfFrameBytes = pollArray(array);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
array.put(buffer, expect);
|
||||||
|
array.removeLastByte(); //移除\n
|
||||||
|
array.removeLastByte(); //移除\r
|
||||||
|
frameList.add(array.getBytes());
|
||||||
|
}
|
||||||
|
} else if (itemType == TYPE_MULTI) { //数组中嵌套数组,例如: SCAN、HSCAN
|
||||||
|
if (size == 2 && frameList != null && frameList.size() == 1) {
|
||||||
|
//读游标 数据例如: *2 $1 0 *4 $4 key1 $2 10 $4 key2 $2 30
|
||||||
|
frameCursor = frameList.get(0);
|
||||||
|
frameList.clear();
|
||||||
|
clearHalfFrame();
|
||||||
|
return readFrames(conn, buffer, array);
|
||||||
|
} else {
|
||||||
|
throw new RedkaleException("Not support multi type in array data");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
halfFrameMultiItemType = 0;
|
||||||
int cha = itemLength - array.length();
|
halfFrameMultiItemLength = Integer.MIN_VALUE;
|
||||||
if (itemLength == -1) {
|
|
||||||
if (frameList == null) {
|
|
||||||
frameList = new ArrayList<>();
|
|
||||||
}
|
|
||||||
frameList.add(null);
|
|
||||||
array.clear();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void clearHalfFrame() {
|
private void clearHalfFrame() {
|
||||||
halfFrameCmd = 0;
|
|
||||||
halfFrameBulkLength = -10;
|
|
||||||
halfFrameArraySize = -10;
|
|
||||||
halfFrameArrayIndex = 0;
|
|
||||||
halfFrameArrayItemLength = -10;
|
|
||||||
halfFrameBytes = null;
|
halfFrameBytes = null;
|
||||||
|
halfFrameBulkLength = Integer.MIN_VALUE;
|
||||||
|
halfFrameMultiSize = Integer.MIN_VALUE;
|
||||||
|
halfFrameMultiItemLength = Integer.MIN_VALUE;
|
||||||
|
halfFrameMultiItemIndex = 0; //从0开始
|
||||||
|
halfFrameMultiItemType = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -207,35 +205,31 @@ public class RedisCacheCodec extends ClientCodec<RedisCacheRequest, RedisCacheRe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ByteBuffer buffer = realbuf;
|
ByteBuffer buffer = realbuf;
|
||||||
if (!checkBytesFrame(conn, buffer, array)) {
|
|
||||||
return;
|
while (buffer.hasRemaining()) {
|
||||||
}
|
if (!readFrames(conn, buffer, array)) {
|
||||||
//buffer必然包含一个完整的frame数据
|
|
||||||
boolean first = true;
|
|
||||||
RedisCacheRequest request = null;
|
|
||||||
while (first || buffer.hasRemaining()) {
|
|
||||||
if (request == null) {
|
|
||||||
request = nextRequest();
|
|
||||||
}
|
|
||||||
if (!first && !checkBytesFrame(conn, buffer, array)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
RedisCacheRequest request = nextRequest();
|
||||||
if (frameType == TYPE_ERROR) {
|
if (frameType == TYPE_ERROR) {
|
||||||
addMessage(request, new RuntimeException(new String(frameValue, StandardCharsets.UTF_8)));
|
addMessage(request, new RedkaleException(new String(frameValue, StandardCharsets.UTF_8)));
|
||||||
} else {
|
} else {
|
||||||
addMessage(request, conn.pollResultSet(request).prepare(frameType, frameValue, frameList));
|
addMessage(request, conn.pollResultSet(request).prepare(frameType, frameCursor, frameValue, frameList));
|
||||||
}
|
}
|
||||||
frameType = 0;
|
frameType = 0;
|
||||||
|
frameCursor = null;
|
||||||
frameValue = null;
|
frameValue = null;
|
||||||
frameList = null;
|
frameList = null;
|
||||||
halfFrameCmd = 0;
|
clearHalfFrame();
|
||||||
halfFrameBytes = null;
|
|
||||||
first = false;
|
|
||||||
buffer = realbuf;
|
buffer = realbuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean readComplete(ByteBuffer buffer, ByteArray array) {
|
protected RedisCacheRequest nextRequest() {
|
||||||
|
return super.nextRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean readComplete(ByteBuffer buffer, ByteArray array) {
|
||||||
while (buffer.hasRemaining()) {
|
while (buffer.hasRemaining()) {
|
||||||
byte b = buffer.get();
|
byte b = buffer.get();
|
||||||
if (b == '\n') {
|
if (b == '\n') {
|
||||||
@ -246,4 +240,16 @@ public class RedisCacheCodec extends ClientCodec<RedisCacheRequest, RedisCacheRe
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int readInt(ByteArray array) {
|
||||||
|
String val = array.toString(StandardCharsets.ISO_8859_1);
|
||||||
|
if (val.length() == 1 && val.charAt(0) == '0') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (val.length() == 2 && val.charAt(0) == '-' && val.charAt(1) == '1') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return Integer.parseInt(val);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,15 @@ import org.redkale.net.WorkThread;
|
|||||||
import org.redkale.net.client.Client;
|
import org.redkale.net.client.Client;
|
||||||
import org.redkale.net.client.ClientCodec;
|
import org.redkale.net.client.ClientCodec;
|
||||||
import org.redkale.net.client.ClientConnection;
|
import org.redkale.net.client.ClientConnection;
|
||||||
|
import org.redkale.net.client.ClientFuture;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCacheConnection extends ClientConnection<RedisCacheRequest, RedisCacheResult> {
|
public class RedisCacheConnection extends ClientConnection<RedisCacheRequest, RedisCacheResult> {
|
||||||
@ -32,18 +36,29 @@ public class RedisCacheConnection extends ClientConnection<RedisCacheRequest, Re
|
|||||||
return super.writeChannel(request);
|
return super.writeChannel(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected CompletableFuture<List<RedisCacheResult>> writeRequest(RedisCacheRequest[] requests) {
|
||||||
|
return super.writeChannel(requests);
|
||||||
|
}
|
||||||
|
|
||||||
protected <T> CompletableFuture<T> writeRequest(RedisCacheRequest request, Function<RedisCacheResult, T> respTransfer) {
|
protected <T> CompletableFuture<T> writeRequest(RedisCacheRequest request, Function<RedisCacheResult, T> respTransfer) {
|
||||||
return super.writeChannel(request, respTransfer);
|
return super.writeChannel(request, respTransfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected <T> CompletableFuture<List<T>> writeRequest(RedisCacheRequest[] requests, Function<RedisCacheResult, T> respTransfer) {
|
||||||
|
return super.writeChannel(requests, respTransfer);
|
||||||
|
}
|
||||||
|
|
||||||
public RedisCacheResult pollResultSet(RedisCacheRequest request) {
|
public RedisCacheResult pollResultSet(RedisCacheRequest request) {
|
||||||
RedisCacheResult rs = new RedisCacheResult();
|
RedisCacheResult rs = new RedisCacheResult();
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RedisCacheRequest pollRequest(WorkThread workThread) {
|
public RedisCacheRequest pollRequest(WorkThread workThread, String traceid) {
|
||||||
RedisCacheRequest rs = new RedisCacheRequest().currThread(workThread);
|
RedisCacheRequest rs = new RedisCacheRequest().workThread(workThread).traceid(traceid);
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ClientFuture<RedisCacheRequest, RedisCacheResult> pollRespFuture(Serializable requestid) {
|
||||||
|
return super.pollRespFuture(requestid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,12 @@ import org.redkale.util.ByteArray;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCacheReqAuth extends RedisCacheRequest {
|
public class RedisCacheReqAuth extends RedisCacheRequest {
|
||||||
|
|
||||||
private static final byte[] PS = "AUTH".getBytes(StandardCharsets.UTF_8);
|
private static final byte[] PS = "AUTH\r\n".getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
protected String password;
|
protected String password;
|
||||||
|
|
||||||
@ -26,20 +27,18 @@ public class RedisCacheReqAuth extends RedisCacheRequest {
|
|||||||
@Override
|
@Override
|
||||||
public void writeTo(ClientConnection conn, ByteArray writer) {
|
public void writeTo(ClientConnection conn, ByteArray writer) {
|
||||||
byte[] pwd = password.getBytes();
|
byte[] pwd = password.getBytes();
|
||||||
writer.put((byte) '*');
|
writer.put(mutliLengthBytes(2));
|
||||||
writer.put((byte) '2');
|
writer.put(bulkLengthBytes(4));
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
|
||||||
writer.put((byte) '$');
|
|
||||||
writer.put((byte) '4');
|
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
|
||||||
writer.put(PS);
|
writer.put(PS);
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
|
||||||
|
|
||||||
writer.put((byte) '$');
|
writer.put(bulkLengthBytes(pwd.length));
|
||||||
writer.put(String.valueOf(pwd.length).getBytes(StandardCharsets.UTF_8));
|
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
|
||||||
writer.put(pwd);
|
writer.put(pwd);
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
writer.put(CRLF);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName() + "{AUTH " + password + "}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
45
src/main/java/org/redkalex/cache/redis/RedisCacheReqClientName.java
vendored
Normal file
45
src/main/java/org/redkalex/cache/redis/RedisCacheReqClientName.java
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkalex.cache.redis;
|
||||||
|
|
||||||
|
import org.redkale.net.client.ClientConnection;
|
||||||
|
import org.redkale.util.ByteArray;
|
||||||
|
import org.redkale.util.Utility;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class RedisCacheReqClientName extends RedisCacheRequest {
|
||||||
|
|
||||||
|
private final String clientName;
|
||||||
|
|
||||||
|
public RedisCacheReqClientName(String appName, String resourceName) {
|
||||||
|
this.clientName = "redkalex" + (Utility.isEmpty(appName) ? "" : ("-" + appName))
|
||||||
|
+ (Utility.isEmpty(resourceName) ? "" : (":" + resourceName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(ClientConnection conn, ByteArray writer) {
|
||||||
|
writer.put(mutliLengthBytes(3));
|
||||||
|
|
||||||
|
writer.put(bulkLengthBytes(6));
|
||||||
|
writer.put("CLIENT\r\n".getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
writer.put(bulkLengthBytes(7));
|
||||||
|
writer.put("SETNAME\r\n".getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
byte[] ns = clientName.getBytes(StandardCharsets.UTF_8);
|
||||||
|
writer.put(bulkLengthBytes(ns.length));
|
||||||
|
writer.put(ns);
|
||||||
|
writer.put(CRLF);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName() + "{CLIENT SETNAME " + clientName + "}";
|
||||||
|
}
|
||||||
|
}
|
@ -11,11 +11,20 @@ import org.redkale.util.ByteArray;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCacheReqClose extends RedisCacheRequest {
|
public class RedisCacheReqClose extends RedisCacheRequest {
|
||||||
|
|
||||||
private static final byte[] PS = "QUIT".getBytes(StandardCharsets.UTF_8);
|
private static final byte[] BYTES = new ByteArray()
|
||||||
|
.put((byte) '*')
|
||||||
|
.put((byte) '1')
|
||||||
|
.put((byte) '\r', (byte) '\n')
|
||||||
|
.put((byte) '$')
|
||||||
|
.put((byte) '4')
|
||||||
|
.put((byte) '\r', (byte) '\n')
|
||||||
|
.put("QUIT".getBytes(StandardCharsets.UTF_8))
|
||||||
|
.put((byte) '\r', (byte) '\n').getBytes();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isCloseType() {
|
public final boolean isCloseType() {
|
||||||
@ -24,13 +33,11 @@ public class RedisCacheReqClose extends RedisCacheRequest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(ClientConnection conn, ByteArray writer) {
|
public void writeTo(ClientConnection conn, ByteArray writer) {
|
||||||
writer.put((byte) '*');
|
writer.put(BYTES);
|
||||||
writer.put((byte) '1');
|
}
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
|
||||||
writer.put((byte) '$');
|
@Override
|
||||||
writer.put((byte) '4');
|
public String toString() {
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
return getClass().getSimpleName() + "{QUIT}";
|
||||||
writer.put(PS);
|
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import org.redkale.util.ByteArray;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCacheReqDB extends RedisCacheRequest {
|
public class RedisCacheReqDB extends RedisCacheRequest {
|
||||||
@ -23,21 +24,19 @@ public class RedisCacheReqDB extends RedisCacheRequest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(ClientConnection conn, ByteArray writer) {
|
public void writeTo(ClientConnection conn, ByteArray writer) {
|
||||||
writer.put((byte) '*');
|
writer.put(mutliLengthBytes(2));
|
||||||
writer.put((byte) '2');
|
writer.put(bulkLengthBytes(6));
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
writer.put("SELECT\r\n".getBytes(StandardCharsets.UTF_8));
|
||||||
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);
|
byte[] dbs = String.valueOf(db).getBytes(StandardCharsets.UTF_8);
|
||||||
writer.put((byte) '$');
|
writer.put(bulkLengthBytes(dbs.length));
|
||||||
writer.put(String.valueOf(dbs.length).getBytes(StandardCharsets.UTF_8));
|
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
|
||||||
writer.put(dbs);
|
writer.put(dbs);
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
writer.put(CRLF);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName() + "{SELECT " + db + "}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,21 +11,28 @@ import org.redkale.util.ByteArray;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCacheReqPing extends RedisCacheRequest {
|
public class RedisCacheReqPing extends RedisCacheRequest {
|
||||||
|
|
||||||
private static final byte[] PS = "PING".getBytes(StandardCharsets.UTF_8);
|
private static final byte[] BYTES = new ByteArray()
|
||||||
|
.put((byte) '*')
|
||||||
|
.put((byte) '1')
|
||||||
|
.put((byte) '\r', (byte) '\n')
|
||||||
|
.put((byte) '$')
|
||||||
|
.put((byte) '4')
|
||||||
|
.put((byte) '\r', (byte) '\n')
|
||||||
|
.put("PING".getBytes(StandardCharsets.UTF_8))
|
||||||
|
.put((byte) '\r', (byte) '\n').getBytes();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(ClientConnection conn, ByteArray writer) {
|
public void writeTo(ClientConnection conn, ByteArray writer) {
|
||||||
writer.put((byte) '*');
|
writer.put(BYTES);
|
||||||
writer.put((byte) '1');
|
}
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
|
||||||
writer.put((byte) '$');
|
@Override
|
||||||
writer.put((byte) '4');
|
public String toString() {
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
return getClass().getSimpleName() + "{PING}";
|
||||||
writer.put(PS);
|
|
||||||
writer.put((byte) '\r', (byte) '\n');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,21 +12,49 @@ import org.redkale.util.ByteArray;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCacheRequest extends ClientRequest {
|
public class RedisCacheRequest extends ClientRequest {
|
||||||
|
|
||||||
static final byte[] TRUE = new byte[]{'t'};
|
static final byte[] BYTES_TRUE = new byte[]{'t'};
|
||||||
|
|
||||||
static final byte[] FALSE = new byte[]{'f'};
|
static final byte[] BYTES_FALSE = new byte[]{'f'};
|
||||||
|
|
||||||
|
static final byte[] BYTES_MATCH = "MATCH".getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
static final byte[] BYTES_COUNT = "COUNT".getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
protected static final byte[] CRLF = new byte[]{'\r', '\n'};
|
||||||
|
|
||||||
|
private static final byte[][] starLengthBytes;
|
||||||
|
|
||||||
|
private static final byte[][] dollarLengthBytes;
|
||||||
|
|
||||||
|
static {
|
||||||
|
starLengthBytes = new byte[1024][];
|
||||||
|
dollarLengthBytes = new byte[1024][];
|
||||||
|
for (int i = 0; i < dollarLengthBytes.length; i++) {
|
||||||
|
starLengthBytes[i] = ("*" + i + "\r\n").getBytes(StandardCharsets.ISO_8859_1);
|
||||||
|
dollarLengthBytes[i] = ("$" + i + "\r\n").getBytes(StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected RedisCommand command;
|
||||||
|
|
||||||
protected String key;
|
protected String key;
|
||||||
|
|
||||||
protected String command;
|
|
||||||
|
|
||||||
protected byte[][] args;
|
protected byte[][] args;
|
||||||
|
|
||||||
public <T> RedisCacheRequest prepare(String command, String key, byte[]... args) {
|
public static RedisCacheRequest create(RedisCommand command, String key, String... args) {
|
||||||
|
return new RedisCacheRequest().prepare(command, key, RedisCacheSource.keysArgs(key, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RedisCacheRequest create(RedisCommand command, String key, byte[]... args) {
|
||||||
|
return new RedisCacheRequest().prepare(command, key, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedisCacheRequest prepare(RedisCommand command, String key, byte[]... args) {
|
||||||
super.prepare();
|
super.prepare();
|
||||||
this.command = command;
|
this.command = command;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
@ -34,28 +62,55 @@ public class RedisCacheRequest extends ClientRequest {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RedisCacheRequest createTime() {
|
||||||
|
this.createTime = System.currentTimeMillis();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(ClientConnection conn, ByteArray writer) {
|
public void writeTo(ClientConnection conn, ByteArray writer) {
|
||||||
writer.put((byte) '*');
|
writer.put(mutliLengthBytes(args.length + 1));
|
||||||
writer.put(String.valueOf(args.length + 1).getBytes(StandardCharsets.UTF_8));
|
writer.put(command.getBytes());
|
||||||
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) {
|
for (final byte[] arg : args) {
|
||||||
writer.put((byte) '$');
|
putArgBytes(writer, arg);
|
||||||
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');
|
protected void putArgBytes(ByteArray writer, byte[] arg) {
|
||||||
|
writer.put(bulkLengthBytes(arg.length));
|
||||||
|
writer.put(arg);
|
||||||
|
writer.put(CRLF);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static byte[] mutliLengthBytes(int length) {
|
||||||
|
if (length >= 0 && length < starLengthBytes.length) {
|
||||||
|
return starLengthBytes[length];
|
||||||
|
} else {
|
||||||
|
return ("*" + length + "\r\n").getBytes(StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static byte[] bulkLengthBytes(int length) {
|
||||||
|
if (length >= 0 && length < dollarLengthBytes.length) {
|
||||||
|
return dollarLengthBytes[length];
|
||||||
|
} else {
|
||||||
|
return ("$" + length + "\r\n").getBytes(StandardCharsets.ISO_8859_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getSimpleName() + "{command=" + command + ", key=" + key + "}";
|
if (args == null || args.length == 0) {
|
||||||
|
return getClass().getSimpleName() + "{" + command + " " + key + "}";
|
||||||
|
} else {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(command);
|
||||||
|
sb.append(" ").append(key);
|
||||||
|
for (final byte[] arg : args) {
|
||||||
|
sb.append(" ").append(arg == null ? null : new String(arg, StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,34 +6,47 @@
|
|||||||
package org.redkalex.cache.redis;
|
package org.redkalex.cache.redis;
|
||||||
|
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
import org.redkale.net.client.ClientResult;
|
||||||
|
import org.redkale.source.CacheScoredValue;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class RedisCacheResult {
|
public class RedisCacheResult implements ClientResult {
|
||||||
|
|
||||||
//+ 简单字符串类型 (不包含CRLF)
|
//$ 块字符串类型
|
||||||
//- 错误类型 (不包含CRLF)
|
|
||||||
//': 整型
|
|
||||||
//$ 块字符串
|
|
||||||
//* 数组
|
//* 数组
|
||||||
|
//+ 简单字符串类型
|
||||||
|
//- 错误类型
|
||||||
|
//: 整型
|
||||||
protected byte frameType;
|
protected byte frameType;
|
||||||
|
|
||||||
protected byte[] frameValue; //(不包含CRLF)
|
protected byte[] frameCursor;
|
||||||
|
|
||||||
protected List<byte[]> frameList; //(不包含CRLF)
|
protected byte[] frameValue;
|
||||||
|
|
||||||
public RedisCacheResult prepare(byte byteType, byte[] val, List<byte[]> bytesList) {
|
protected List<byte[]> frameList;
|
||||||
|
|
||||||
|
public RedisCacheResult prepare(byte byteType, byte[] frameCursor, byte[] frameValue, List<byte[]> frameList) {
|
||||||
this.frameType = byteType;
|
this.frameType = byteType;
|
||||||
this.frameValue = val;
|
this.frameCursor = frameCursor;
|
||||||
this.frameList = bytesList;
|
this.frameValue = frameValue;
|
||||||
|
this.frameList = frameList;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isKeepAlive() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public Void getVoidValue() {
|
public Void getVoidValue() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -42,6 +55,14 @@ public class RedisCacheResult {
|
|||||||
return frameValue;
|
return frameValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCursor() {
|
||||||
|
if (frameCursor == null || frameCursor.length < 1) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return Integer.parseInt(new String(frameCursor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Boolean getBoolValue() {
|
public Boolean getBoolValue() {
|
||||||
if (frameValue == null) {
|
if (frameValue == null) {
|
||||||
return false;
|
return false;
|
||||||
@ -50,34 +71,73 @@ public class RedisCacheResult {
|
|||||||
if ("OK".equals(val)) {
|
if ("OK".equals(val)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (val.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (char ch : val.toCharArray()) {
|
||||||
|
if (!Character.isDigit(ch)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return Integer.parseInt(val) > 0;
|
return Integer.parseInt(val) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStringValue(String key, RedisCryptor cryptor) {
|
public Double getDoubleValue(Double defValue) {
|
||||||
if (frameValue == null) {
|
if (frameValue == null) {
|
||||||
return null;
|
return defValue;
|
||||||
}
|
}
|
||||||
String val = new String(frameValue, StandardCharsets.UTF_8);
|
String val = new String(frameValue, StandardCharsets.UTF_8);
|
||||||
if (cryptor != null) {
|
if ("nan".equalsIgnoreCase(val) || "-nan".equalsIgnoreCase(val)) {
|
||||||
val = cryptor.decrypt(key, val);
|
return Double.NaN;
|
||||||
|
} else if ("inf".equalsIgnoreCase(val)) {
|
||||||
|
return Double.POSITIVE_INFINITY;
|
||||||
|
} else if ("-inf".equalsIgnoreCase(val)) {
|
||||||
|
return Double.NEGATIVE_INFINITY;
|
||||||
|
} else if ("-1".equalsIgnoreCase(val)) {
|
||||||
|
return -1.0;
|
||||||
|
} else if ("0".equalsIgnoreCase(val)) {
|
||||||
|
return 0.0;
|
||||||
|
} else if ("1".equalsIgnoreCase(val)) {
|
||||||
|
return 1.0;
|
||||||
|
} else {
|
||||||
|
return Double.parseDouble(val);
|
||||||
}
|
}
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Double getDoubleValue(Double defvalue) {
|
public Long getLongValue(Long defValue) {
|
||||||
return frameValue == null ? defvalue : Double.parseDouble(new String(frameValue, StandardCharsets.UTF_8));
|
if (frameValue == null) {
|
||||||
|
return defValue;
|
||||||
|
}
|
||||||
|
String val = new String(frameValue, StandardCharsets.UTF_8);
|
||||||
|
if ("-1".equalsIgnoreCase(val)) {
|
||||||
|
return -1L;
|
||||||
|
} else if ("0".equalsIgnoreCase(val)) {
|
||||||
|
return 0L;
|
||||||
|
} else if ("1".equalsIgnoreCase(val)) {
|
||||||
|
return 1L;
|
||||||
|
} else {
|
||||||
|
return Long.parseLong(val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getLongValue(Long defvalue) {
|
public Integer getIntValue(Integer defValue) {
|
||||||
return frameValue == null ? defvalue : Long.parseLong(new String(frameValue, StandardCharsets.UTF_8));
|
if (frameValue == null) {
|
||||||
}
|
return defValue;
|
||||||
|
}
|
||||||
public Integer getIntValue(Integer defvalue) {
|
String val = new String(frameValue, StandardCharsets.UTF_8);
|
||||||
return frameValue == null ? defvalue : Integer.parseInt(new String(frameValue, StandardCharsets.UTF_8));
|
if ("-1".equalsIgnoreCase(val)) {
|
||||||
|
return -1;
|
||||||
|
} else if ("0".equalsIgnoreCase(val)) {
|
||||||
|
return 0;
|
||||||
|
} else if ("1".equalsIgnoreCase(val)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return Integer.parseInt(val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getObjectValue(String key, RedisCryptor cryptor, Type type) {
|
public <T> T getObjectValue(String key, RedisCryptor cryptor, Type type) {
|
||||||
return formatValue(key, cryptor, frameValue, type);
|
return decodeValue(key, cryptor, frameValue, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> Set<T> getSetValue(String key, RedisCryptor cryptor, Type type) {
|
protected <T> Set<T> getSetValue(String key, RedisCryptor cryptor, Type type) {
|
||||||
@ -86,7 +146,23 @@ public class RedisCacheResult {
|
|||||||
}
|
}
|
||||||
Set<T> set = new LinkedHashSet<>();
|
Set<T> set = new LinkedHashSet<>();
|
||||||
for (byte[] bs : frameList) {
|
for (byte[] bs : frameList) {
|
||||||
set.add(formatValue(key, cryptor, bs, type));
|
set.add(decodeValue(key, cryptor, bs, type));
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<CacheScoredValue> getScoreListValue(String key, RedisCryptor cryptor, Type scoreType) {
|
||||||
|
if (frameList == null || frameList.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
List<CacheScoredValue> set = new ArrayList<>();
|
||||||
|
for (int i = 0; i < frameList.size(); i += 2) {
|
||||||
|
byte[] bs1 = frameList.get(i);
|
||||||
|
byte[] bs2 = frameList.get(i + 1);
|
||||||
|
Number val = decodeValue(key, cryptor, bs2, scoreType);
|
||||||
|
if (val != null) {
|
||||||
|
set.add(CacheScoredValue.create(val, new String(bs1, StandardCharsets.UTF_8)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
@ -97,7 +173,7 @@ public class RedisCacheResult {
|
|||||||
}
|
}
|
||||||
List<T> list = new ArrayList<>();
|
List<T> list = new ArrayList<>();
|
||||||
for (byte[] bs : frameList) {
|
for (byte[] bs : frameList) {
|
||||||
list.add(formatValue(key, cryptor, bs, type));
|
list.add(decodeValue(key, cryptor, bs, type));
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@ -110,15 +186,15 @@ public class RedisCacheResult {
|
|||||||
for (int i = 0; i < frameList.size(); i += 2) {
|
for (int i = 0; i < frameList.size(); i += 2) {
|
||||||
byte[] bs1 = frameList.get(i);
|
byte[] bs1 = frameList.get(i);
|
||||||
byte[] bs2 = frameList.get(i + 1);
|
byte[] bs2 = frameList.get(i + 1);
|
||||||
T val = formatValue(key, cryptor, bs2, type);
|
T val = decodeValue(key, cryptor, bs2, type);
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
map.put(formatValue(key, cryptor, bs1, String.class).toString(), val);
|
map.put(decodeValue(key, cryptor, bs1, String.class).toString(), val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static <T> T formatValue(String key, RedisCryptor cryptor, byte[] frames, Type type) {
|
protected static <T> T decodeValue(String key, RedisCryptor cryptor, byte[] frames, Type type) {
|
||||||
if (frames == null) {
|
if (frames == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -132,12 +208,25 @@ public class RedisCacheResult {
|
|||||||
}
|
}
|
||||||
return (T) val;
|
return (T) val;
|
||||||
}
|
}
|
||||||
if (type == boolean.class || type == Boolean.class) {
|
if (type == int.class || type == Integer.class) {
|
||||||
return (T) (Boolean) "t".equalsIgnoreCase(new String(frames, StandardCharsets.UTF_8));
|
return (T) (Integer) Integer.parseInt(new String(frames, StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
if (type == long.class || type == Long.class) {
|
if (type == long.class || type == Long.class) {
|
||||||
return (T) (Long) Long.parseLong(new String(frames, StandardCharsets.UTF_8));
|
return (T) (Long) Long.parseLong(new String(frames, StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
if (type == float.class || type == Float.class) {
|
||||||
|
return (T) (Float) Float.parseFloat(new String(frames, StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
if (type == BigInteger.class) {
|
||||||
|
return (T) new BigInteger(new String(frames, StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
if (type == BigDecimal.class) {
|
||||||
|
return (T) new BigDecimal(new String(frames, StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
if (type == boolean.class || type == Boolean.class) {
|
||||||
|
String v = new String(frames, StandardCharsets.UTF_8);
|
||||||
|
return (T) (Boolean) ("t".equalsIgnoreCase(v) || "1".equals(v));
|
||||||
|
}
|
||||||
if (type == double.class || type == Double.class) {
|
if (type == double.class || type == Double.class) {
|
||||||
return (T) (Double) Double.parseDouble(new String(frames, StandardCharsets.UTF_8));
|
return (T) (Double) Double.parseDouble(new String(frames, StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
@ -148,4 +237,26 @@ public class RedisCacheResult {
|
|||||||
return (T) JsonConvert.root().convertFrom(type, frames);
|
return (T) JsonConvert.root().convertFrom(type, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("{type: ").append(frameType);
|
||||||
|
if (frameValue != null) {
|
||||||
|
sb.append(", value: ").append(new String(frameValue, StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
if (frameList != null) {
|
||||||
|
sb.append(", list: [");
|
||||||
|
boolean first = true;
|
||||||
|
for (byte[] bs : frameList) {
|
||||||
|
if (!first) {
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
sb.append(bs == null ? null : new String(bs, StandardCharsets.UTF_8));
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
sb.append("]");
|
||||||
|
}
|
||||||
|
return sb.append("}").toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -11,19 +11,20 @@ import org.redkale.source.CacheSourceProvider;
|
|||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@Priority(1)
|
@Priority(-900)
|
||||||
public class RedisCacheSourceProvider implements CacheSourceProvider {
|
public class RedisCacheSourceProvider implements CacheSourceProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptsConf(AnyValue config) {
|
public boolean acceptsConf(AnyValue config) {
|
||||||
return new MyRedisCacheSource().acceptsConf(config);
|
return new RedisCacheSource().acceptsConf(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CacheSource createInstance() {
|
public CacheSource createInstance() {
|
||||||
return new MyRedisCacheSource();
|
return new RedisCacheSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
124
src/main/java/org/redkalex/cache/redis/RedisCommand.java
vendored
Normal file
124
src/main/java/org/redkalex/cache/redis/RedisCommand.java
vendored
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkalex.cache.redis;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public enum RedisCommand {
|
||||||
|
|
||||||
|
EXISTS("EXISTS", true),
|
||||||
|
GET("GET", true),
|
||||||
|
GETEX("GETEX", true),
|
||||||
|
MSET("MSET", false),
|
||||||
|
SET("SET", false),
|
||||||
|
SETNX("SETNX", false),
|
||||||
|
GETSET("GETSET", false),
|
||||||
|
GETDEL("GETDEL", false),
|
||||||
|
SETEX("SETEX", false),
|
||||||
|
EXPIRE("EXPIRE", false),
|
||||||
|
PERSIST("PERSIST", false),
|
||||||
|
RENAME("RENAME", false),
|
||||||
|
RENAMENX("RENAMENX", false),
|
||||||
|
DEL("DEL", false),
|
||||||
|
INCR("INCR", false),
|
||||||
|
INCRBY("INCRBY", false),
|
||||||
|
INCRBYFLOAT("INCRBYFLOAT", false),
|
||||||
|
DECR("DECR", false),
|
||||||
|
DECRBY("DECRBY", false),
|
||||||
|
HDEL("HDEL", false),
|
||||||
|
HINCRBY("HINCRBY", false),
|
||||||
|
HINCRBYFLOAT("HINCRBYFLOAT", false),
|
||||||
|
LINSERT("LINSERT", false),
|
||||||
|
LTRIM("LTRIM", false),
|
||||||
|
LPOP("LPOP", false),
|
||||||
|
LPUSH("LPUSH", false),
|
||||||
|
LPUSHX("LPUSHX", false),
|
||||||
|
RPOP("RPOP", false),
|
||||||
|
RPOPLPUSH("RPOPLPUSH", false),
|
||||||
|
SMOVE("SMOVE", false),
|
||||||
|
RPUSH("RPUSH", false),
|
||||||
|
RPUSHX("RPUSHX", false),
|
||||||
|
LREM("LREM", false),
|
||||||
|
SADD("SADD", false),
|
||||||
|
SPOP("SPOP", false),
|
||||||
|
SSCAN("SSCAN", true),
|
||||||
|
SREM("SREM", false),
|
||||||
|
ZADD("ZADD", false),
|
||||||
|
ZINCRBY("ZINCRBY", false),
|
||||||
|
ZREM("ZREM", false),
|
||||||
|
ZMSCORE("ZMSCORE", true),
|
||||||
|
ZSCORE("ZSCORE", true),
|
||||||
|
ZCARD("ZCARD", true),
|
||||||
|
ZRANK("ZRANK", true),
|
||||||
|
ZREVRANK("ZREVRANK", true),
|
||||||
|
ZRANGE("ZRANGE", true),
|
||||||
|
ZSCAN("ZSCAN", true),
|
||||||
|
FLUSHDB("FLUSHDB", false),
|
||||||
|
FLUSHALL("FLUSHALL", false),
|
||||||
|
HMGET("HMGET", true),
|
||||||
|
HLEN("HLEN", true),
|
||||||
|
HKEYS("HKEYS", true),
|
||||||
|
HEXISTS("HEXISTS", true),
|
||||||
|
HSET("HSET", true),
|
||||||
|
HSETNX("HSETNX", true),
|
||||||
|
HMSET("HMSET", true),
|
||||||
|
HSCAN("HSCAN", true),
|
||||||
|
HGETALL("HGETALL", true),
|
||||||
|
HVALS("HVALS", true),
|
||||||
|
HGET("HGET", true),
|
||||||
|
HSTRLEN("HSTRLEN", true),
|
||||||
|
SMEMBERS("SMEMBERS", true),
|
||||||
|
SISMEMBER("SISMEMBER", true),
|
||||||
|
LRANGE("LRANGE", true),
|
||||||
|
LINDEX("LINDEX", true),
|
||||||
|
LLEN("LLEN", true),
|
||||||
|
SCARD("SCARD", true),
|
||||||
|
SMISMEMBER("SMISMEMBER", true),
|
||||||
|
SRANDMEMBER("SRANDMEMBER", true),
|
||||||
|
SDIFF("SDIFF", true),
|
||||||
|
SDIFFSTORE("SDIFFSTORE", false),
|
||||||
|
SINTER("SINTER", true),
|
||||||
|
SINTERSTORE("SINTERSTORE", false),
|
||||||
|
SUNION("SUNION", true),
|
||||||
|
SUNIONSTORE("SUNIONSTORE", false),
|
||||||
|
MGET("MGET", true),
|
||||||
|
KEYS("KEYS", true),
|
||||||
|
SCAN("SCAN", true),
|
||||||
|
DBSIZE("DBSIZE", true),
|
||||||
|
TYPE("TYPE", true),
|
||||||
|
SUBSCRIBE("SUBSCRIBE", false),
|
||||||
|
UNSUBSCRIBE("UNSUBSCRIBE", false),
|
||||||
|
PUBLISH("PUBLISH", false),
|
||||||
|
PUBSUB("PUBSUB", true),
|
||||||
|
GETBIT("GETBIT", true),
|
||||||
|
SETBIT("SETBIT", false),
|
||||||
|
EVAL("EVAL", false);
|
||||||
|
|
||||||
|
private final String command;
|
||||||
|
|
||||||
|
private final byte[] bytes;
|
||||||
|
|
||||||
|
private final boolean readOnly;
|
||||||
|
|
||||||
|
private RedisCommand(String command, boolean readOnly) {
|
||||||
|
this.command = command;
|
||||||
|
this.readOnly = readOnly;
|
||||||
|
this.bytes = ("$" + command.length() + "\r\n" + command + "\r\n").getBytes(StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getBytes() {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReadOnly() {
|
||||||
|
return readOnly;
|
||||||
|
}
|
||||||
|
}
|
190
src/main/java/org/redkalex/cache/redis/RedisConfig.java
vendored
Normal file
190
src/main/java/org/redkalex/cache/redis/RedisConfig.java
vendored
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkalex.cache.redis;
|
||||||
|
|
||||||
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
import org.redkale.util.AnyValue;
|
||||||
|
import org.redkale.util.RedkaleException;
|
||||||
|
import org.redkale.util.Utility;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.redkale.source.AbstractCacheSource.*;
|
||||||
|
import static org.redkale.util.Utility.isEmpty;
|
||||||
|
import static org.redkale.util.Utility.isNotEmpty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class RedisConfig {
|
||||||
|
|
||||||
|
private boolean ssl;
|
||||||
|
|
||||||
|
private int db;
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private int maxconns;
|
||||||
|
|
||||||
|
private int pipelines;
|
||||||
|
|
||||||
|
private List<String> addresses;
|
||||||
|
|
||||||
|
public static RedisConfig create(AnyValue conf) {
|
||||||
|
RedisConfig result = new RedisConfig();
|
||||||
|
int gdb = conf.getIntValue(CACHE_SOURCE_DB, 0);
|
||||||
|
String gusername = null;
|
||||||
|
String gpassword = conf.getValue(CACHE_SOURCE_PASSWORD);
|
||||||
|
int gmaxconns = conf.getIntValue(CACHE_SOURCE_MAXCONNS, Utility.cpus());
|
||||||
|
int gpipelines = conf.getIntValue(CACHE_SOURCE_PIPELINES, org.redkale.net.client.Client.DEFAULT_MAX_PIPELINES);
|
||||||
|
String nodes = conf.getValue(CACHE_SOURCE_NODES, conf.getValue("url", ""));
|
||||||
|
if (Utility.isEmpty(nodes)) {
|
||||||
|
throw new RedkaleException("Not found nodes config for redis");
|
||||||
|
}
|
||||||
|
List<String> addrs = new ArrayList<>();
|
||||||
|
for (String url : nodes.replace(',', ';').split(";")) {
|
||||||
|
String urluser = null;
|
||||||
|
String urlpwd = null;
|
||||||
|
String urldb = null;
|
||||||
|
String urlmaxconns = null;
|
||||||
|
String urlpipelines = null;
|
||||||
|
addrs.add(url);
|
||||||
|
if (url.startsWith("redis://")) { //兼容 redis://:1234@127.0.0.1:6379?db=2
|
||||||
|
URI uri = URI.create(url);
|
||||||
|
String userInfo = uri.getUserInfo();
|
||||||
|
if (isEmpty(userInfo)) {
|
||||||
|
String authority = uri.getAuthority();
|
||||||
|
if (authority != null && authority.indexOf('@') > 0) {
|
||||||
|
userInfo = authority.substring(0, authority.indexOf('@'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNotEmpty(userInfo)) {
|
||||||
|
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 (isNotEmpty(uri.getQuery())) {
|
||||||
|
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 ? "" : qrys[i + 1];
|
||||||
|
} else if (CACHE_SOURCE_PIPELINES.equals(qrys[i])) {
|
||||||
|
urlpipelines = i == qrys.length - 1 ? "" : qrys[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNotEmpty(urluser)) {
|
||||||
|
gusername = urluser;
|
||||||
|
}
|
||||||
|
if (isNotEmpty(urlpwd)) {
|
||||||
|
gpassword = urlpwd;
|
||||||
|
}
|
||||||
|
if (isNotEmpty(urlmaxconns)) {
|
||||||
|
gmaxconns = Integer.parseInt(urlmaxconns);
|
||||||
|
}
|
||||||
|
if (isNotEmpty(urlpipelines)) {
|
||||||
|
gpipelines = Integer.parseInt(urlpipelines);
|
||||||
|
}
|
||||||
|
if (isNotEmpty(urldb)) {
|
||||||
|
gdb = Integer.parseInt(urldb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.ssl = nodes.startsWith("rediss://");
|
||||||
|
result.db = gdb;
|
||||||
|
if (isNotEmpty(gusername)) {
|
||||||
|
result.username = gusername;
|
||||||
|
}
|
||||||
|
if (isNotEmpty(gpassword)) {
|
||||||
|
result.password = gpassword;
|
||||||
|
}
|
||||||
|
result.maxconns = gmaxconns;
|
||||||
|
result.pipelines = gpipelines;
|
||||||
|
result.addresses = addrs;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSsl() {
|
||||||
|
return ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSsl(boolean ssl) {
|
||||||
|
this.ssl = ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDb() {
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDb(int db) {
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxconns() {
|
||||||
|
return maxconns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxconns(int min) {
|
||||||
|
return Math.max(maxconns, min);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxconns(int maxconns) {
|
||||||
|
this.maxconns = maxconns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPipelines() {
|
||||||
|
return pipelines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPipelines(int pipelines) {
|
||||||
|
this.pipelines = pipelines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAddresses() {
|
||||||
|
return addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddresses(List<String> addresses) {
|
||||||
|
this.addresses = addresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JsonConvert.root().convertTo(this);
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ package org.redkalex.cache.redis;
|
|||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public interface RedisCryptor {
|
public interface RedisCryptor {
|
||||||
@ -23,6 +24,7 @@ public interface RedisCryptor {
|
|||||||
*
|
*
|
||||||
* @param key key
|
* @param key key
|
||||||
* @param value 明文
|
* @param value 明文
|
||||||
|
*
|
||||||
* @return 密文
|
* @return 密文
|
||||||
*/
|
*/
|
||||||
public String encrypt(String key, String value);
|
public String encrypt(String key, String value);
|
||||||
@ -32,6 +34,7 @@ public interface RedisCryptor {
|
|||||||
*
|
*
|
||||||
* @param key key
|
* @param key key
|
||||||
* @param value 密文
|
* @param value 密文
|
||||||
|
*
|
||||||
* @return 明文
|
* @return 明文
|
||||||
*/
|
*/
|
||||||
public String decrypt(String key, String value);
|
public String decrypt(String key, String value);
|
||||||
|
@ -1 +1 @@
|
|||||||
net.tccn.ZhubProvider
|
dev.zhub.ZhubProvider
|
@ -1,7 +1,7 @@
|
|||||||
package net.tccn.mq;
|
package net.tccn.mq;
|
||||||
|
|
||||||
import net.tccn.Event;
|
import net.tccn.Event;
|
||||||
import net.tccn.timer.Timers;
|
import dev.zhub.timer.Timers;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
|
||||||
|
@ -27,15 +27,15 @@ public class HelloService implements Service {
|
|||||||
@Resource(name = "vvvvhub2")
|
@Resource(name = "vvvvhub2")
|
||||||
private ZHubClient zhub2;*/
|
private ZHubClient zhub2;*/
|
||||||
|
|
||||||
//private net.tccn.zhub.ZHubClient zhubx = null;
|
//private dev.zhub.client.ZHubClient zhubx = null;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(AnyValue config) {
|
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 dev.zhub.client.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");
|
//zhubx = new dev.zhub.client.ZHubClient("47.111.150.118", 6066, "g-dev", "DEV-LOCAL");
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
// Function<Rpc<T>, RpcResult<R>> fun
|
// Function<Rpc<T>, RpcResult<R>> fun
|
||||||
|
Loading…
Reference in New Issue
Block a user