Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 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>2.1.0.BUILD-SNAPSHOT</version>
<version>2.1.0.DATAREDIS-529-SNAPSHOT</version>

<name>Spring Data Redis</name>

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -303,6 +294,24 @@ public Boolean exists(byte[] key) {
return convertAndReturn(delegate.exists(key), identityConverter);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.StringRedisConnection#exists(String[])
*/
@Override
public Long exists(String... keys) {
return convertAndReturn(delegate.exists(serializeMulti(keys)), identityConverter);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#exists(byte[][])
*/
@Override
public Long exists(byte[]... keys) {
return convertAndReturn(delegate.exists(keys), identityConverter);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#expire(byte[], long)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ default Boolean exists(byte[] key) {
return keyCommands().exists(key);
}

/** @deprecated in favor of {@link RedisConnection#keyCommands()}. */
@Override
@Deprecated
default Long exists(byte[]... keys) {
return keyCommands().exists(keys);
}

/** @deprecated in favor of {@link RedisConnection#keyCommands()}. */
@Override
@Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
* Key-specific commands supported by Redis.
Expand All @@ -40,7 +41,24 @@ public interface RedisKeyCommands {
* @see <a href="http://redis.io/commands/exists">Redis Documentation: EXISTS</a>
*/
@Nullable
Boolean exists(byte[] key);
default Boolean exists(byte[] key) {

Assert.notNull(key, "Key must not be null!");
Long count = exists(new byte[][] { key });
return count != null ? count > 0 : null;
}

/**
* Count how many of the given {@code keys} exist. Providing the very same {@code key} more than once also counts
* multiple times.
*
* @param keys must not be {@literal null}.
* @return the number of keys existing among the ones specified as arguments. {@literal null} when used in pipeline /
* transaction.
* @since 2.1
*/
@Nullable
Long exists(byte[]... keys);

/**
* Delete given {@code keys}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ interface StringTuple extends Tuple {
*/
Boolean exists(String key);

/**
* Count how many of the given {@code keys} exist.
*
* @param keys must not be {@literal null}.
* @return
* @see <a href="http://redis.io/commands/exists">Redis Documentation: EXISTS</a>
* @see RedisKeyCommands#exists(byte[][])
* @since 2.1
*/
@Nullable
Long exists(String... keys);

/**
* Delete given {@code keys}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package org.springframework.data.redis.connection.jedis;

import redis.clients.jedis.BinaryJedis;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand All @@ -37,8 +39,10 @@
import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisMultiKeyClusterCommandCallback;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

/**
* @author Christoph Strobl
Expand All @@ -60,7 +64,8 @@ class JedisClusterKeyCommands implements RedisKeyCommands {
@Override
public Long del(byte[]... keys) {

Assert.noNullElements(keys, "Keys must not be null or contain null key!");
Assert.notNull(keys, "Keys must not be null!");
Assert.noNullElements(keys, "Keys must not contain null elements!");

if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
try {
Expand Down Expand Up @@ -471,18 +476,26 @@ public Long sort(byte[] key, SortParameters params, byte[] storeKey) {

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#exists(byte[])
* @see org.springframework.data.redis.connection.RedisKeyCommands#exists(byte[][])
*/
@Nullable
@Override
public Boolean exists(byte[] key) {
public Long exists(byte[]... keys) {

Assert.notNull(key, "Key must not be null!");
Assert.notNull(keys, "Keys must not be null!");
Assert.noNullElements(keys, "Keys must not contain null elements!");

try {
return connection.getCluster().exists(key);
} catch (Exception ex) {
throw convertJedisAccessException(ex);
if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
try {
return connection.getCluster().exists(keys);
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}

return connection.getClusterCommandExecutor()
.executeMultiKeyCommand((JedisMultiKeyClusterCommandCallback<Boolean>) BinaryJedis::exists, Arrays.asList(keys))
.resultsAsList().stream().mapToLong(val -> ObjectUtils.nullSafeEquals(val, Boolean.TRUE) ? 1 : 0).sum();
}

private DataAccessException convertJedisAccessException(Exception ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,34 @@ public Boolean exists(byte[] key) {
}
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#exists(byte[][])
*/
@Nullable
@Override
public Long exists(byte[]... keys) {

Assert.notNull(keys, "Keys must not be null!");
Assert.noNullElements(keys, "Keys must not contain null elements!");

try {
if (isPipelined()) {
pipeline(
connection.newJedisResult(connection.getRequiredPipeline().exists(keys)));
return null;
}
if (isQueueing()) {
transaction(connection
.newJedisResult(connection.getRequiredTransaction().exists(keys)));
return null;
}
return connection.getJedis().exists(keys);
} catch (Exception ex) {
throw connection.convertJedisAccessException(ex);
}
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#del(byte[][])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.springframework.data.redis.core.ScanCursor;
import org.springframework.data.redis.core.ScanIteration;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
Expand Down Expand Up @@ -76,6 +77,32 @@ public Boolean exists(byte[] key) {
}
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#exists(byte[][])
*/
@Nullable
@Override
public Long exists(byte[]... keys) {

Assert.notNull(keys, "Keys must not be null!");
Assert.noNullElements(keys, "Keys must not contain null elements!");

try {
if (isPipelined()) {
pipeline(connection.newLettuceResult(getAsyncConnection().exists(keys)));
return null;
}
if (isQueueing()) {
transaction(connection.newLettuceTxResult(getAsyncConnection().exists(keys)));
return null;
}
return getConnection().exists(keys);
} catch (Exception ex) {
throw convertLettuceAccessException(ex);
}
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisKeyCommands#del(byte[][])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,18 @@ <T> T execute(RedisScript<T> script, RedisSerializer<?> argsSerializer, RedisSer
@Nullable
Boolean hasKey(K key);

/**
* Count the number of {@code keys} that exists.
*
* @param keys must not be {@literal null}.
* @return The number of keys existing among the ones specified as arguments. Keys mentioned multiple times and
* existing are counted multiple times.
* @see <a href="http://redis.io/commands/exists">Redis Documentation: EXISTS</a>
* @since 2.1
*/
@Nullable
Long countExistingKeys(Collection<K> keys);

/**
* Delete given {@code key}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,19 @@ public Boolean hasKey(K key) {
return execute(connection -> connection.exists(rawKey), true);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#countExistingKeys(java.util.Collection)
*/
@Override
public Long countExistingKeys(Collection<K> keys) {

Assert.notNull(keys, "Keys must not be null!");

byte[][] rawKeys = rawKeys(keys);
return execute(connection -> connection.exists(rawKeys), true);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#expire(java.lang.Object, long, java.util.concurrent.TimeUnit)
Expand Down Expand Up @@ -1313,7 +1326,7 @@ public void setEnableTransactionSupport(boolean enableTransactionSupport) {
* Set the {@link ClassLoader} to be used for the default {@link JdkSerializationRedisSerializer} in case no other
* {@link RedisSerializer} is explicitly set as the default one.
*
* @param resourceLoader can be {@literal null}.
* @param classLoader can be {@literal null}.
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader
* @since 1.8
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,36 @@ public void testExists() {
verifyResults(Arrays.asList(new Object[] { true, false }));
}

@Test // DATAREDIS-529
public void testExistsWithMultipleKeys() {

connection.set("exist-1", "true");
connection.set("exist-2", "true");
connection.set("exist-3", "true");

actual.add(connection.exists("exist-1", "exist-2", "exist-3", "nonexistent"));

verifyResults(Arrays.asList(new Object[] { 3L }));
}

@Test // DATAREDIS-529
public void testExistsWithMultipleKeysNoneExists() {

actual.add(connection.exists("no-exist-1", "no-exist-2"));

verifyResults(Arrays.asList(new Object[] { 0L }));
}

@Test // DATAREDIS-529
public void testExistsSameKeyMultipleTimes() {

connection.set("existent", "true");

actual.add(connection.exists("existent", "existent"));

verifyResults(Arrays.asList(new Object[] { 2L }));
}

@SuppressWarnings("unchecked")
@Test
public void testKeys() throws Exception {
Expand Down
Loading