Skip to content

Commit 1e4cd6f

Browse files
mp911dechristophstrobl
authored andcommitted
Upgrade to Jedis 4.2.
The upgrade also allows to enable support for GEOSEARCH, GEOSEARCHSTORE, XCLAIMJUSTID and XPENDING. Closes: #2212 Original Pull Request: #2287
1 parent d3a70f8 commit 1e4cd6f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1144
-1467
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<xstream>1.4.19</xstream>
2525
<pool>2.11.1</pool>
2626
<lettuce>6.1.8.RELEASE</lettuce>
27-
<jedis>3.8.0</jedis>
27+
<jedis>4.2.0</jedis>
2828
<multithreadedtc>1.01</multithreadedtc>
2929
<netty>4.1.72.Final</netty>
3030
<java-module-name>spring.data.redis</java-module-name>

src/main/java/org/springframework/data/redis/connection/convert/SetConverter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.redis.connection.convert;
1717

18+
import java.util.Collection;
1819
import java.util.LinkedHashSet;
1920
import java.util.Set;
2021
import java.util.stream.Collectors;
@@ -48,4 +49,8 @@ public Set<T> convert(Set<S> source) {
4849
return source.stream().map(itemConverter::convert).collect(Collectors.toCollection(LinkedHashSet::new));
4950
}
5051

52+
public Set<T> convert(Collection<S> source) {
53+
return source.stream().map(itemConverter::convert).collect(Collectors.toCollection(LinkedHashSet::new));
54+
}
55+
5156
}

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

Lines changed: 27 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@
1515
*/
1616
package org.springframework.data.redis.connection.jedis;
1717

18-
import redis.clients.jedis.Builder;
19-
import redis.clients.jedis.Client;
18+
import redis.clients.jedis.Connection;
2019
import redis.clients.jedis.Jedis;
21-
import redis.clients.jedis.Protocol.Command;
22-
import redis.clients.jedis.Queable;
23-
import redis.clients.jedis.Response;
24-
import redis.clients.jedis.util.SafeEncoder;
20+
import redis.clients.jedis.Protocol;
21+
import redis.clients.jedis.Transaction;
2522

26-
import java.lang.reflect.Method;
23+
import java.lang.reflect.Field;
24+
import java.nio.charset.StandardCharsets;
2725
import java.util.Arrays;
2826
import java.util.Set;
2927
import java.util.function.Function;
@@ -43,26 +41,15 @@
4341
@SuppressWarnings({ "unchecked", "ConstantConditions" })
4442
class JedisClientUtils {
4543

46-
private static final Method GET_RESPONSE;
44+
private static final Field TRANSACTION;
4745
private static final Set<String> KNOWN_COMMANDS;
48-
private static final Builder<Object> OBJECT_BUILDER;
4946

5047
static {
5148

52-
GET_RESPONSE = ReflectionUtils.findMethod(Queable.class, "getResponse", Builder.class);
53-
ReflectionUtils.makeAccessible(GET_RESPONSE);
49+
TRANSACTION = ReflectionUtils.findField(Jedis.class, "transaction");
50+
ReflectionUtils.makeAccessible(TRANSACTION);
5451

55-
KNOWN_COMMANDS = Arrays.stream(Command.values()).map(Enum::name).collect(Collectors.toSet());
56-
57-
OBJECT_BUILDER = new Builder<Object>() {
58-
public Object build(Object data) {
59-
return data;
60-
}
61-
62-
public String toString() {
63-
return "Object";
64-
}
65-
};
52+
KNOWN_COMMANDS = Arrays.stream(Protocol.Command.values()).map(Enum::name).collect(Collectors.toSet());
6653
}
6754

6855
/**
@@ -72,7 +59,7 @@ public String toString() {
7259
* @param keys must not be {@literal null}, may be empty.
7360
* @param args must not be {@literal null}, may be empty.
7461
* @param jedis must not be {@literal null}.
75-
* @return the response, can be be {@literal null}.
62+
* @return the response, can be {@literal null}.
7663
*/
7764
static <T> T execute(String command, byte[][] keys, byte[][] args, Supplier<Jedis> jedis) {
7865
return execute(command, keys, args, jedis, it -> (T) it.getOne());
@@ -86,42 +73,42 @@ static <T> T execute(String command, byte[][] keys, byte[][] args, Supplier<Jedi
8673
* @param args must not be {@literal null}, may be empty.
8774
* @param jedis must not be {@literal null}.
8875
* @param responseMapper must not be {@literal null}.
89-
* @return the response, can be be {@literal null}.
76+
* @return the response, can be {@literal null}.
9077
* @since 2.1
9178
*/
9279
static <T> T execute(String command, byte[][] keys, byte[][] args, Supplier<Jedis> jedis,
93-
Function<Client, T> responseMapper) {
80+
Function<Connection, T> responseMapper) {
9481

9582
byte[][] commandArgs = getCommandArguments(keys, args);
9683

97-
Client client = sendCommand(command, commandArgs, jedis.get());
84+
Connection Connection = sendCommand(command, commandArgs, jedis.get());
9885

99-
return responseMapper.apply(client);
86+
return responseMapper.apply(Connection);
10087
}
10188

10289
/**
103-
* Send a Redis command and retrieve the {@link Client} for response retrieval.
90+
* Send a Redis command and retrieve the {@link Connection} for response retrieval.
10491
*
10592
* @param command the command.
10693
* @param args must not be {@literal null}, may be empty.
10794
* @param jedis must not be {@literal null}.
108-
* @return the {@link Client} instance used to send the command.
95+
* @return the {@link Connection} instance used to send the command.
10996
*/
110-
static Client sendCommand(String command, byte[][] args, Jedis jedis) {
97+
static Connection sendCommand(String command, byte[][] args, Jedis jedis) {
11198

112-
Client client = jedis.getClient();
99+
Connection Connection = jedis.getConnection();
113100

114-
sendCommand(client, command, args);
101+
sendCommand(Connection, command, args);
115102

116-
return client;
103+
return Connection;
117104
}
118105

119-
private static void sendCommand(Client client, String command, byte[][] args) {
106+
private static void sendCommand(Connection Connection, String command, byte[][] args) {
120107

121108
if (isKnownCommand(command)) {
122-
client.sendCommand(Command.valueOf(command.trim().toUpperCase()), args);
109+
Connection.sendCommand(Protocol.Command.valueOf(command.trim().toUpperCase()), args);
123110
} else {
124-
client.sendCommand(() -> SafeEncoder.encode(command.trim().toUpperCase()), args);
111+
Connection.sendCommand(() -> command.trim().toUpperCase().getBytes(StandardCharsets.UTF_8), args);
125112
}
126113
}
127114

@@ -148,23 +135,13 @@ private static byte[][] getCommandArguments(byte[][] keys, byte[][] args) {
148135
}
149136

150137
/**
151-
* @param jedis the client instance.
138+
* @param jedis the Connection instance.
152139
* @return {@literal true} if the connection has entered {@literal MULTI} state.
153140
*/
154141
static boolean isInMulti(Jedis jedis) {
155-
return jedis.getClient().isInMulti();
156-
}
157142

158-
/**
159-
* Retrieve the {@link Response} object from a {@link redis.clients.jedis.Transaction} or a
160-
* {@link redis.clients.jedis.Pipeline} for response synchronization.
161-
*
162-
* @param target a {@link redis.clients.jedis.Transaction} or {@link redis.clients.jedis.Pipeline}, must not be
163-
* {@literal null}.
164-
* @return the {@link Response} wrapper object.
165-
*/
166-
static Response<Object> getResponse(Object target) {
167-
return (Response<Object>) ReflectionUtils.invokeMethod(GET_RESPONSE, target, OBJECT_BUILDER);
168-
}
143+
Object field = ReflectionUtils.getField(TRANSACTION, jedis);
169144

145+
return field instanceof Transaction;
146+
}
170147
}

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

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@
1515
*/
1616
package org.springframework.data.redis.connection.jedis;
1717

18-
import redis.clients.jedis.BinaryJedis;
19-
import redis.clients.jedis.Client;
18+
import redis.clients.jedis.Connection;
19+
import redis.clients.jedis.ConnectionPool;
2020
import redis.clients.jedis.HostAndPort;
2121
import redis.clients.jedis.Jedis;
2222
import redis.clients.jedis.JedisCluster;
23-
import redis.clients.jedis.JedisClusterConnectionHandler;
24-
import redis.clients.jedis.JedisPool;
23+
import redis.clients.jedis.providers.ClusterConnectionProvider;
2524

2625
import java.time.Duration;
2726
import java.util.ArrayList;
@@ -33,7 +32,6 @@
3332
import java.util.Map;
3433
import java.util.Map.Entry;
3534
import java.util.Set;
36-
import java.util.function.Function;
3735

3836
import org.apache.commons.logging.Log;
3937
import org.apache.commons.logging.LogFactory;
@@ -119,9 +117,13 @@ public JedisClusterConnection(JedisCluster cluster) {
119117
new JedisClusterNodeResourceProvider(cluster, topologyProvider), EXCEPTION_TRANSLATION);
120118
disposeClusterCommandExecutorOnClose = true;
121119

120+
122121
try {
123-
DirectFieldAccessor dfa = new DirectFieldAccessor(cluster);
124-
clusterCommandExecutor.setMaxRedirects((Integer) dfa.getPropertyValue("maxRedirections"));
122+
123+
DirectFieldAccessor executorDfa = new DirectFieldAccessor(cluster);
124+
Object custerCommandExecutor = executorDfa.getPropertyValue("executor");
125+
DirectFieldAccessor dfa = new DirectFieldAccessor(custerCommandExecutor);
126+
clusterCommandExecutor.setMaxRedirects((Integer) dfa.getPropertyValue("maxRedirects"));
125127
} catch (Exception e) {
126128
// ignore it and work with the executor default
127129
}
@@ -177,11 +179,6 @@ public Object execute(String command, byte[]... args) {
177179
@Nullable
178180
@Override
179181
public <T> T execute(String command, byte[] key, Collection<byte[]> args) {
180-
return execute(command, key, args, it -> (T) it.getOne());
181-
}
182-
183-
@Nullable
184-
<T> T execute(String command, byte[] key, Collection<byte[]> args, Function<Client, T> responseMapper) {
185182

186183
Assert.notNull(command, "Command must not be null!");
187184
Assert.notNull(key, "Key must not be null!");
@@ -191,8 +188,9 @@ <T> T execute(String command, byte[] key, Collection<byte[]> args, Function<Clie
191188

192189
RedisClusterNode keyMaster = topologyProvider.getTopology().getKeyServingMasterNode(key);
193190

194-
return clusterCommandExecutor.executeCommandOnSingleNode((JedisClusterCommandCallback<T>) client -> JedisClientUtils
195-
.execute(command, EMPTY_2D_BYTE_ARRAY, commandArgs, () -> client, responseMapper), keyMaster).getValue();
191+
return clusterCommandExecutor.executeCommandOnSingleNode((JedisClusterCommandCallback<T>) client -> {
192+
return (T) client.sendCommand(() -> JedisConverters.toBytes(command), commandArgs);
193+
}, keyMaster).getValue();
196194
}
197195

198196
private static byte[][] getCommandArguments(byte[] key, Collection<byte[]> args) {
@@ -409,18 +407,13 @@ public void select(int dbIndex) {
409407

410408
@Override
411409
public byte[] echo(byte[] message) {
412-
413-
try {
414-
return cluster.echo(message);
415-
} catch (Exception ex) {
416-
throw convertJedisAccessException(ex);
417-
}
410+
throw new InvalidDataAccessApiUsageException("Echo not supported in cluster mode.");
418411
}
419412

420413
@Override
421414
public String ping() {
422415

423-
return !clusterCommandExecutor.executeCommandOnAllNodes((JedisClusterCommandCallback<String>) BinaryJedis::ping)
416+
return !clusterCommandExecutor.executeCommandOnAllNodes((JedisClusterCommandCallback<String>) Jedis::ping)
424417
.resultsAsList().isEmpty() ? "PONG" : null;
425418

426419
}
@@ -429,7 +422,7 @@ public String ping() {
429422
public String ping(RedisClusterNode node) {
430423

431424
return clusterCommandExecutor
432-
.executeCommandOnSingleNode((JedisClusterCommandCallback<String>) BinaryJedis::ping, node).getValue();
425+
.executeCommandOnSingleNode((JedisClusterCommandCallback<String>) Jedis::ping, node).getValue();
433426
}
434427

435428
/*
@@ -552,8 +545,10 @@ public void clusterReplicate(RedisClusterNode master, RedisClusterNode replica)
552545
@Override
553546
public Integer clusterGetSlotForKey(byte[] key) {
554547

555-
return clusterCommandExecutor.executeCommandOnArbitraryNode((JedisClusterCommandCallback<Integer>) client -> client
556-
.clusterKeySlot(JedisConverters.toString(key)).intValue()).getValue();
548+
return clusterCommandExecutor
549+
.executeCommandOnArbitraryNode(
550+
(JedisClusterCommandCallback<Integer>) client -> (int) client.clusterKeySlot(JedisConverters.toString(key)))
551+
.getValue();
557552
}
558553

559554
@Override
@@ -709,7 +704,7 @@ static class JedisClusterNodeResourceProvider implements ClusterNodeResourceProv
709704

710705
private final JedisCluster cluster;
711706
private final ClusterTopologyProvider topologyProvider;
712-
private final JedisClusterConnectionHandler connectionHandler;
707+
private final ClusterConnectionProvider connectionHandler;
713708

714709
/**
715710
* Creates new {@link JedisClusterNodeResourceProvider}.
@@ -726,7 +721,7 @@ static class JedisClusterNodeResourceProvider implements ClusterNodeResourceProv
726721

727722
PropertyAccessor accessor = new DirectFieldAccessFallbackBeanWrapper(cluster);
728723
this.connectionHandler = accessor.isReadableProperty("connectionHandler")
729-
? (JedisClusterConnectionHandler) accessor.getPropertyValue("connectionHandler")
724+
? (ClusterConnectionProvider) accessor.getPropertyValue("connectionHandler")
730725
: null;
731726
} else {
732727
this.connectionHandler = null;
@@ -739,31 +734,31 @@ public Jedis getResourceForSpecificNode(RedisClusterNode node) {
739734

740735
Assert.notNull(node, "Cannot get Pool for 'null' node!");
741736

742-
JedisPool pool = getResourcePoolForSpecificNode(node);
737+
ConnectionPool pool = getResourcePoolForSpecificNode(node);
743738
if (pool != null) {
744-
return pool.getResource();
739+
return new Jedis(pool.getResource());
745740
}
746741

747-
Jedis connection = getConnectionForSpecificNode(node);
742+
Connection connection = getConnectionForSpecificNode(node);
748743

749744
if (connection != null) {
750-
return connection;
745+
return new Jedis(connection);
751746
}
752747

753748
throw new DataAccessResourceFailureException(String.format("Node %s is unknown to cluster", node));
754749
}
755750

756-
private JedisPool getResourcePoolForSpecificNode(RedisClusterNode node) {
751+
private ConnectionPool getResourcePoolForSpecificNode(RedisClusterNode node) {
757752

758-
Map<String, JedisPool> clusterNodes = cluster.getClusterNodes();
753+
Map<String, ConnectionPool> clusterNodes = cluster.getClusterNodes();
759754
if (clusterNodes.containsKey(node.asString())) {
760755
return clusterNodes.get(node.asString());
761756
}
762757

763758
return null;
764759
}
765760

766-
private Jedis getConnectionForSpecificNode(RedisClusterNode node) {
761+
private Connection getConnectionForSpecificNode(RedisClusterNode node) {
767762

768763
RedisClusterNode member = topologyProvider.getTopology().lookup(node);
769764

@@ -773,7 +768,7 @@ private Jedis getConnectionForSpecificNode(RedisClusterNode node) {
773768
}
774769

775770
if (member != null && connectionHandler != null) {
776-
return connectionHandler.getConnectionFromNode(new HostAndPort(member.getHost(), member.getPort()));
771+
return connectionHandler.getConnection(new HostAndPort(member.getHost(), member.getPort()));
777772
}
778773

779774
return null;
@@ -835,15 +830,15 @@ public ClusterTopology getTopology() {
835830

836831
Map<String, Exception> errors = new LinkedHashMap<>();
837832

838-
List<Entry<String, JedisPool>> list = new ArrayList<>(cluster.getClusterNodes().entrySet());
833+
List<Entry<String, ConnectionPool>> list = new ArrayList<>(cluster.getClusterNodes().entrySet());
839834
Collections.shuffle(list);
840835

841-
for (Entry<String, JedisPool> entry : list) {
836+
for (Entry<String, ConnectionPool> entry : list) {
842837

843-
try (Jedis jedis = entry.getValue().getResource()) {
838+
try (Connection connection = entry.getValue().getResource()) {
844839

845840
time = System.currentTimeMillis();
846-
Set<RedisClusterNode> nodes = Converters.toSetOfRedisClusterNodes(jedis.clusterNodes());
841+
Set<RedisClusterNode> nodes = Converters.toSetOfRedisClusterNodes(new Jedis(connection).clusterNodes());
847842

848843
synchronized (lock) {
849844
cached = new ClusterTopology(nodes);

0 commit comments

Comments
 (0)