Skip to content

Commit a58eec0

Browse files
committed
DATAREDIS-1005 - Support Eval & EvalSha commands by JedisClusterConnection.
Added Integration test.
1 parent c7298f6 commit a58eec0

File tree

3 files changed

+80
-6
lines changed

3 files changed

+80
-6
lines changed

src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterConnection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ public RedisClusterServerCommands serverCommands() {
326326
*/
327327
@Override
328328
public RedisScriptingCommands scriptingCommands() {
329-
return JedisClusterScriptingCommands.INSTANCE;
329+
return new JedisClusterScriptingCommands(this);
330330
}
331331

332332
private JedisClusterKeyCommands doGetKeyCommands() {

src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterScriptingCommands.java

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,22 @@
1717

1818
import java.util.List;
1919

20+
import lombok.NonNull;
21+
import lombok.RequiredArgsConstructor;
22+
import org.springframework.dao.DataAccessException;
2023
import org.springframework.dao.InvalidDataAccessApiUsageException;
2124
import org.springframework.data.redis.connection.RedisScriptingCommands;
2225
import org.springframework.data.redis.connection.ReturnType;
26+
import redis.clients.jedis.JedisCluster;
2327

2428
/**
2529
* @author Mark Paluch
2630
* @since 2.0
2731
*/
28-
enum JedisClusterScriptingCommands implements RedisScriptingCommands {
32+
@RequiredArgsConstructor
33+
class JedisClusterScriptingCommands implements RedisScriptingCommands {
2934

30-
INSTANCE;
35+
private final @NonNull JedisClusterConnection clusterConnection;
3136

3237
/*
3338
* (non-Javadoc)
@@ -70,8 +75,15 @@ public List<Boolean> scriptExists(String... scriptShas) {
7075
* @see org.springframework.data.redis.connection.RedisScriptingCommands#eval(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][])
7176
*/
7277
@Override
78+
@SuppressWarnings("unchecked")
7379
public <T> T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... keysAndArgs) {
74-
throw new InvalidDataAccessApiUsageException("Eval is not supported in cluster environment.");
80+
checkConnection();
81+
try {
82+
return (T) new JedisScriptReturnConverter(returnType)
83+
.convert(getCluster().eval(script, JedisConverters.toBytes(numKeys), keysAndArgs));
84+
} catch (Exception ex) {
85+
throw convertJedisAccessException(ex);
86+
}
7587
}
7688

7789
/*
@@ -80,15 +92,51 @@ public <T> T eval(byte[] script, ReturnType returnType, int numKeys, byte[]... k
8092
*/
8193
@Override
8294
public <T> T evalSha(String scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) {
83-
throw new InvalidDataAccessApiUsageException("EvalSha is not supported in cluster environment.");
95+
return evalSha(JedisConverters.toBytes(scriptSha), returnType, numKeys, keysAndArgs);
8496
}
8597

8698
/*
8799
* (non-Javadoc)
88100
* @see org.springframework.data.redis.connection.RedisScriptingCommands#evalSha(byte[], org.springframework.data.redis.connection.ReturnType, int, byte[][])
89101
*/
90102
@Override
103+
@SuppressWarnings("unchecked")
91104
public <T> T evalSha(byte[] scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) {
92-
throw new InvalidDataAccessApiUsageException("EvalSha is not supported in cluster environment.");
105+
checkConnection();
106+
try {
107+
return (T) new JedisScriptReturnConverter(returnType)
108+
.convert(getCluster().evalsha(scriptSha, numKeys, keysAndArgs));
109+
} catch (Exception ex) {
110+
throw convertJedisAccessException(ex);
111+
}
112+
}
113+
114+
public JedisClusterConnection getClusterConnection() {
115+
return clusterConnection;
116+
}
117+
118+
protected RuntimeException convertJedisAccessException(Exception ex) {
119+
return clusterConnection.convertJedisAccessException(ex);
120+
}
121+
122+
private JedisCluster getCluster() {
123+
return clusterConnection.getCluster();
124+
}
125+
126+
protected void checkConnection() {
127+
if (isQueueing()) {
128+
throw new UnsupportedOperationException();
129+
}
130+
if (isPipelined()) {
131+
throw new UnsupportedOperationException();
132+
}
133+
}
134+
135+
private boolean isPipelined() {
136+
return clusterConnection.isPipelined();
137+
}
138+
139+
private boolean isQueueing() {
140+
return clusterConnection.isQueueing();
93141
}
94142
}

src/test/java/org/springframework/data/redis/connection/jedis/JedisClusterConnectionTests.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.springframework.data.redis.connection.ClusterConnectionTests;
5252
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
5353
import org.springframework.data.redis.connection.DataType;
54+
import org.springframework.data.redis.connection.ReturnType;
5455
import org.springframework.data.redis.connection.DefaultSortParameters;
5556
import org.springframework.data.redis.connection.DefaultTuple;
5657
import org.springframework.data.redis.connection.RedisClusterNode;
@@ -70,6 +71,7 @@
7071
import org.springframework.data.redis.test.util.MinimumRedisVersionRule;
7172
import org.springframework.data.redis.test.util.RedisClusterRule;
7273
import org.springframework.test.annotation.IfProfileValue;
74+
import org.springframework.data.redis.core.script.DigestUtils;
7375

7476
/**
7577
* @author Christoph Strobl
@@ -2421,4 +2423,28 @@ public void bitfieldShouldWorkUsingNonZeroBasedOffset() {
24212423
.valueAt(offset(0L).multipliedByTypeLength())
24222424
.get(INT_8).valueAt(offset(1L).multipliedByTypeLength())), contains(100L, -56L));
24232425
}
2426+
2427+
@Test // DATAREDIS-1005
2428+
@IfProfileValue(name = "redisVersion", value = "2.6+")
2429+
public void evalOK() {
2430+
byte[] keyAndArgs = JedisConverters.toBytes("FOO");
2431+
2432+
String luaScript = "return redis.call(\"INCR\", KEYS[1])";
2433+
byte[] luaScriptBin = JedisConverters.toBytes(luaScript);
2434+
Long result = clusterConnection.scriptingCommands().eval(luaScriptBin, ReturnType.VALUE, 1, keyAndArgs);
2435+
assertThat(result, is(1L));
2436+
}
2437+
2438+
@Test // DATAREDIS-1005
2439+
@IfProfileValue(name = "redisVersion", value = "2.6+")
2440+
public void evalShaOK() {
2441+
byte[] keyAndArgs = JedisConverters.toBytes("FOO");
2442+
2443+
String luaScript = "return redis.call(\"INCR\", KEYS[1])";
2444+
String digest = DigestUtils.sha1DigestAsHex(luaScript);
2445+
byte[] luaScriptBin = JedisConverters.toBytes(digest);
2446+
Long result = clusterConnection.scriptingCommands().evalSha(luaScriptBin, ReturnType.VALUE, 1, keyAndArgs);
2447+
assertThat(result, is(1L));
2448+
}
2449+
24242450
}

0 commit comments

Comments
 (0)