Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Jedis 5.0 #2716

Closed
wants to merge 9 commits into from
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-GH-2612-SNAPSHOT</version>

<name>Spring Data Redis</name>
<description>Spring Data module for Redis</description>
Expand All @@ -25,7 +25,7 @@
<xstream>1.4.20</xstream>
<pool>2.11.1</pool>
<lettuce>6.2.6.RELEASE</lettuce>
<jedis>4.4.4</jedis>
<jedis>5.0.1</jedis>
<multithreadedtc>1.01</multithreadedtc>
<netty>4.1.96.Final</netty>
<java-module-name>spring.data.redis</java-module-name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,25 @@
import org.springframework.lang.Nullable;

/**
* The result of an asynchronous operation
* Result of an asynchronous operation
*
* @param <T> The data type of the object that holds the future result (usually type of the
* {@link java.util.concurrent.Future} or response wrapper).
* @author Jennifer Hickey
* @author Christoph Strobl
* @author Mark Paluch
* @param <T> The data type of the object that holds the future result (usually type of the
* {@link java.util.concurrent.Future} or response wrapper).
* @author John Blum
*/
public abstract class FutureResult<T> {

private T resultHolder;
private boolean status = false;

private final T resultHolder;

private final Supplier<?> defaultConversionResult;

private boolean status = false;

@SuppressWarnings("rawtypes") //
@SuppressWarnings("rawtypes")
protected Converter converter;

/**
Expand Down Expand Up @@ -71,23 +74,14 @@ public FutureResult(T resultHolder, @Nullable Converter converter) {
* @param defaultConversionResult must not be {@literal null}.
* @since 2.1
*/
@SuppressWarnings("rawtypes")
public FutureResult(T resultHolder, @Nullable Converter converter, Supplier<?> defaultConversionResult) {

this.resultHolder = resultHolder;
this.converter = converter != null ? converter : val -> val;
this.defaultConversionResult = defaultConversionResult;
}

/**
* Get the object holding the actual result.
*
* @return never {@literal null}.
* @since 1.1
*/
public T getResultHolder() {
return resultHolder;
}

/**
* Converts the given result if a converter is specified, else returns the result
*
Expand All @@ -98,11 +92,9 @@ public T getResultHolder() {
@Nullable
public Object convert(@Nullable Object result) {

if (result == null) {
return computeDefaultResult(null);
}
Object resolvedResult = result != null ? getConverter().convert(result) : null;

return computeDefaultResult(converter.convert(result));
return computeDefaultResult(resolvedResult);
}

@Nullable
Expand All @@ -112,7 +104,17 @@ private Object computeDefaultResult(@Nullable Object source) {

@SuppressWarnings("rawtypes")
public Converter getConverter() {
return converter;
return this.converter;
}

/**
* Get the object holding the actual result.
*
* @return never {@literal null}.
* @since 1.1
*/
public T getResultHolder() {
return this.resultHolder;
}

/**
Expand All @@ -121,7 +123,7 @@ public Converter getConverter() {
* @return true if this is a status result (i.e. OK)
*/
public boolean isStatus() {
return status;
return this.status;
}

/**
Expand All @@ -144,4 +146,5 @@ public void setStatus(boolean status) {
* @since 2.1
*/
public abstract boolean conversionRequired();

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@
import org.springframework.data.redis.core.ScanCursor;
import org.springframework.data.redis.core.ScanIteration;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.util.Streamable;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
* Cluster {@link RedisHashCommands} implementation for Jedis.
*
* @author Christoph Strobl
* @author Mark Paluch
* @author John Blum
* @since 2.0
*/
class JedisClusterHashCommands implements RedisHashCommands {
Expand Down Expand Up @@ -160,10 +162,10 @@ public Entry<byte[], byte[]> hRandFieldWithValues(byte[] key) {
Assert.notNull(key, "Key must not be null");

try {
Map<byte[], byte[]> map = connection.getCluster().hrandfieldWithValues(key, 1);
return map.isEmpty() ? null : map.entrySet().iterator().next();
} catch (Exception ex) {
throw convertJedisAccessException(ex);
List<Entry<byte[], byte[]>> mapEntryList = connection.getCluster().hrandfieldWithValues(key, 1);
return mapEntryList.isEmpty() ? null : mapEntryList.get(0);
} catch (Exception cause) {
throw convertJedisAccessException(cause);
}
}

Expand All @@ -185,10 +187,9 @@ public List<byte[]> hRandField(byte[] key, long count) {
public List<Entry<byte[], byte[]>> hRandFieldWithValues(byte[] key, long count) {

try {
Map<byte[], byte[]> map = connection.getCluster().hrandfieldWithValues(key, count);
return Streamable.of(() -> map.entrySet().iterator()).toList();
} catch (Exception ex) {
throw convertJedisAccessException(ex);
return connection.getCluster().hrandfieldWithValues(key, count);
} catch (Exception cause) {
throw convertJedisAccessException(cause);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@
*/
package org.springframework.data.redis.connection.jedis;

import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
Expand All @@ -38,9 +37,14 @@
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import redis.clients.jedis.Jedis;

/**
* {@link RedisClusterServerCommands} implementation for Jedis.
*
* @author Mark Paluch
* @author Dennis Neufeld
* @author John Blum
* @since 2.0
*/
class JedisClusterServerCommands implements RedisClusterServerCommands {
Expand Down Expand Up @@ -82,7 +86,8 @@ public Long lastSave() {
return null;
}

Collections.sort(result, Collections.reverseOrder());
result.sort(Collections.reverseOrder());

return result.get(0);
}

Expand Down Expand Up @@ -221,20 +226,20 @@ public Properties info(RedisClusterNode node, String section) {
public void shutdown() {
connection.getClusterCommandExecutor().executeCommandOnAllNodes((JedisClusterCommandCallback<String>) jedis -> {
jedis.shutdown();
return null;
return "success";
});
}

@Override
public void shutdown(RedisClusterNode node) {
executeCommandOnSingleNode(jedis -> {
jedis.shutdown();
return null;
return "success";
}, node);
}

@Override
public void shutdown(ShutdownOption option) {
public void shutdown(@Nullable ShutdownOption option) {

if (option == null) {
shutdown();
Expand All @@ -249,32 +254,37 @@ public Properties getConfig(String pattern) {

Assert.notNull(pattern, "Pattern must not be null");

List<NodeResult<List<String>>> mapResult = connection.getClusterCommandExecutor()
.executeCommandOnAllNodes((JedisClusterCommandCallback<List<String>>) client -> client.configGet(pattern))
JedisClusterCommandCallback<Map<String, String>> command = jedis -> jedis.configGet(pattern);

List<NodeResult<Map<String, String>>> nodeResults = connection.getClusterCommandExecutor()
.executeCommandOnAllNodes(command)
.getResults();

List<String> result = new ArrayList<>();
for (NodeResult<List<String>> entry : mapResult) {
Properties nodesConfiguration = new Properties();

for (NodeResult<Map<String, String>> nodeResult : nodeResults) {

String prefix = nodeResult.getNode().asString();

String prefix = entry.getNode().asString();
int i = 0;
for (String value : entry.getValue()) {
result.add((i++ % 2 == 0 ? (prefix + ".") : "") + value);
for (Entry<String, String> entry : nodeResult.getValue().entrySet()) {
String newKey = prefix.concat(".").concat(entry.getKey());
String value = entry.getValue();
nodesConfiguration.setProperty(newKey, value);
}
}

return Converters.toProperties(result);
return nodesConfiguration;
}

@Override
public Properties getConfig(RedisClusterNode node, String pattern) {

Assert.notNull(pattern, "Pattern must not be null");

JedisClusterCommandCallback<Properties> command = client -> Converters.toProperties(client.configGet(pattern));

return connection.getClusterCommandExecutor()
.executeCommandOnSingleNode(
(JedisClusterCommandCallback<Properties>) client -> Converters.toProperties(client.configGet(pattern)),
node)
.executeCommandOnSingleNode(command, node)
.getValue();
}

Expand Down Expand Up @@ -322,19 +332,19 @@ public void rewriteConfig(RedisClusterNode node) {
@Override
public Long time(TimeUnit timeUnit) {

return convertListOfStringToTime(
connection.getClusterCommandExecutor()
.executeCommandOnArbitraryNode((JedisClusterCommandCallback<List<String>>) Jedis::time).getValue(),
timeUnit);
JedisClusterCommandCallback<List<String>> command = Jedis::time;

return convertListOfStringToTime(connection.getClusterCommandExecutor()
.executeCommandOnArbitraryNode(command).getValue(), timeUnit);
}

@Override
public Long time(RedisClusterNode node, TimeUnit timeUnit) {

return convertListOfStringToTime(
connection.getClusterCommandExecutor()
.executeCommandOnSingleNode((JedisClusterCommandCallback<List<String>>) Jedis::time, node).getValue(),
timeUnit);
JedisClusterCommandCallback<List<String>> command = Jedis::time;

return convertListOfStringToTime(connection.getClusterCommandExecutor()
.executeCommandOnSingleNode(command, node).getValue(), timeUnit);
}

@Override
Expand All @@ -343,8 +353,9 @@ public void killClient(String host, int port) {
Assert.hasText(host, "Host for 'CLIENT KILL' must not be 'null' or 'empty'");
String hostAndPort = String.format("%s:%s", host, port);

connection.getClusterCommandExecutor()
.executeCommandOnAllNodes((JedisClusterCommandCallback<String>) client -> client.clientKill(hostAndPort));
JedisClusterCommandCallback<String> command = jedis -> jedis.clientKill(hostAndPort);

connection.getClusterCommandExecutor().executeCommandOnAllNodes(command);
}

@Override
Expand All @@ -360,21 +371,26 @@ public String getClientName() {
@Override
public List<RedisClientInfo> getClientList() {

JedisClusterCommandCallback<String> command = Jedis::clientList;

Collection<String> map = connection.getClusterCommandExecutor()
.executeCommandOnAllNodes((JedisClusterCommandCallback<String>) Jedis::clientList).resultsAsList();
.executeCommandOnAllNodes(command).resultsAsList();

ArrayList<RedisClientInfo> result = new ArrayList<>();

for (String infos : map) {
result.addAll(JedisConverters.toListOfRedisClientInformation(infos));
}

return result;
}

@Override
public List<RedisClientInfo> getClientList(RedisClusterNode node) {

return JedisConverters
.toListOfRedisClientInformation(executeCommandOnSingleNode(Jedis::clientList, node).getValue());
JedisClusterCommandCallback<String> command = Jedis::clientList;

return JedisConverters.toListOfRedisClientInformation(executeCommandOnSingleNode(command, node).getValue());
}

@Override
Expand Down Expand Up @@ -403,8 +419,10 @@ public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable Migrate

RedisClusterNode node = connection.getTopologyProvider().getTopology().lookup(target.getHost(), target.getPort());

executeCommandOnSingleNode(client -> client.migrate(target.getHost(), target.getPort(), key, dbIndex, timeoutToUse),
node);
JedisClusterCommandCallback<String> command = jedis ->
jedis.migrate(target.getHost(), target.getPort(), key, dbIndex, timeoutToUse);

executeCommandOnSingleNode(command, node);
}

private Long convertListOfStringToTime(List<String> serverTimeInformation, TimeUnit timeUnit) {
Expand All @@ -416,12 +434,11 @@ private Long convertListOfStringToTime(List<String> serverTimeInformation, TimeU
return Converters.toTimeMillis(serverTimeInformation.get(0), serverTimeInformation.get(1), timeUnit);
}

private <T> NodeResult<T> executeCommandOnSingleNode(JedisClusterCommandCallback<T> cmd, RedisClusterNode node) {
return connection.getClusterCommandExecutor().executeCommandOnSingleNode(cmd, node);
private <T> NodeResult<T> executeCommandOnSingleNode(JedisClusterCommandCallback<T> command, RedisClusterNode node) {
return connection.getClusterCommandExecutor().executeCommandOnSingleNode(command, node);
}

private <T> MultiNodeResult<T> executeCommandOnAllNodes(JedisClusterCommandCallback<T> cmd) {
return connection.getClusterCommandExecutor().executeCommandOnAllNodes(cmd);
private <T> MultiNodeResult<T> executeCommandOnAllNodes(JedisClusterCommandCallback<T> command) {
return connection.getClusterCommandExecutor().executeCommandOnAllNodes(command);
}

}
Loading