Skip to content

Commit 79ee7fd

Browse files
AnneMayorpranne1224
authored andcommitted
Add multiple reactive keys exist checker
1 parent 06f3591 commit 79ee7fd

File tree

6 files changed

+86
-7
lines changed

6 files changed

+86
-7
lines changed

src/main/java/org/springframework/data/redis/connection/ReactiveKeyCommands.java

+8
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,14 @@ default Mono<Boolean> exists(ByteBuffer key) {
175175

176176
return exists(Mono.just(new KeyCommand(key))).next().map(BooleanResponse::getOutput);
177177
}
178+
/**
179+
* Determine the number of given {@literal keys} that exist.
180+
*
181+
* @param keys must not be {@literal null} or {@literal empty}.
182+
* @return {@link Mono} emitting {@literal the number of existing keys}.
183+
* @see <a href="https://redis.io/docs/commands/exists/">Redis Documentation: EXISTS</a>
184+
*/
185+
Mono<Long> exists(List<ByteBuffer> keys);
178186

179187
/**
180188
* Determine if given {@literal key} exists.

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java

+8
Original file line numberDiff line numberDiff line change
@@ -319,4 +319,12 @@ public Mono<Duration> idletime(ByteBuffer key) {
319319
public Mono<Long> refcount(ByteBuffer key) {
320320
return connection.execute(cmd -> cmd.objectRefcount(key)).next();
321321
}
322+
323+
@Override
324+
public Mono<Long> exists(List<ByteBuffer> keys) {
325+
Assert.notNull(keys, "Key list must not be null");
326+
Assert.notEmpty(keys, "Key list must not be empty");
327+
328+
return connection.execute(cmd -> cmd.exists(keys.toArray(ByteBuffer[]::new))).next();
329+
}
322330
}

src/main/java/org/springframework/data/redis/core/ReactiveRedisOperations.java

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.time.Duration;
2323
import java.time.Instant;
2424
import java.util.Arrays;
25+
import java.util.Collection;
2526
import java.util.Collections;
2627
import java.util.List;
2728

@@ -402,6 +403,15 @@ default Flux<K> scan() {
402403
*/
403404
Mono<Duration> getExpire(K key);
404405

406+
/**
407+
* Get the number of given {@code keys} that exists.
408+
*
409+
* @param keys must not be {@literal null} or {@literal empty}.
410+
* @return the number of existing keys in redis. 0 if there are no existing keys.
411+
* @see <a href="https://redis.io/docs/commands/exists/">Redis Documentation: EXISTS</a>
412+
*/
413+
Mono<Long> countExistingKeys(Collection<K> keys);
414+
405415
// -------------------------------------------------------------------------
406416
// Methods dealing with Redis Lua scripts
407417
// -------------------------------------------------------------------------

src/main/java/org/springframework/data/redis/core/ReactiveRedisTemplate.java

+20
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.time.Duration;
2424
import java.time.Instant;
2525
import java.util.Arrays;
26+
import java.util.Collection;
2627
import java.util.List;
2728
import java.util.stream.Collectors;
2829

@@ -489,6 +490,14 @@ public Mono<Boolean> move(K key, int dbIndex) {
489490
return doCreateMono(connection -> connection.keyCommands().move(rawKey(key), dbIndex));
490491
}
491492

493+
@Override
494+
public Mono<Long> countExistingKeys(Collection<K> keys) {
495+
Assert.notNull(keys, "Keys must not be null");
496+
497+
ByteBuffer[] rawKeys = rawKeys(keys);
498+
return doCreateMono(connection -> connection.keyCommands().exists(Arrays.asList(rawKeys)));
499+
}
500+
492501
// -------------------------------------------------------------------------
493502
// Methods dealing with Redis Lua scripts
494503
// -------------------------------------------------------------------------
@@ -672,6 +681,17 @@ private ByteBuffer rawKey(K key) {
672681
return getSerializationContext().getKeySerializationPair().getWriter().write(key);
673682
}
674683

684+
private ByteBuffer[] rawKeys(Collection<K> keys) {
685+
final ByteBuffer[] rawKeys = new ByteBuffer[keys.size()];
686+
687+
int i = 0;
688+
for (K key : keys) {
689+
rawKeys[i++] = rawKey(key);
690+
}
691+
692+
return rawKeys;
693+
}
694+
675695
@Nullable
676696
private K readKey(ByteBuffer buffer) {
677697
return getSerializationContext().getKeySerializationPair().getReader().read(buffer);

src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommandsIntegrationTests.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,22 @@ void existsShouldReturnFalseForNonExistingKeys() {
6666
connection.keyCommands().exists(KEY_1_BBUFFER).as(StepVerifier::create).expectNext(false).verifyComplete();
6767
}
6868

69+
@ParameterizedRedisTest
70+
void existsKeyReturnsKeyCount() {
71+
nativeCommands.set(KEY_1, "1000");
72+
nativeCommands.set(KEY_2, "2000");
73+
nativeCommands.set(KEY_3, "3000");
74+
75+
connection.keyCommands().exists(List.of(KEY_1_BBUFFER, KEY_2_BBUFFER, KEY_3_BBUFFER)).as(StepVerifier::create)
76+
.expectNext(3L).verifyComplete();
77+
}
78+
79+
@ParameterizedRedisTest
80+
void existsKeyReturnsZeroWhenKeyDoesNotExist() {
81+
connection.keyCommands().exists(List.of(KEY_1_BBUFFER, KEY_2_BBUFFER, KEY_3_BBUFFER)).as(StepVerifier::create)
82+
.expectNext(0L).verifyComplete();
83+
}
84+
6985
@ParameterizedRedisTest // DATAREDIS-525
7086
void typeShouldReturnTypeCorrectly() {
7187

@@ -164,7 +180,7 @@ void renameShouldAlterKeyNameCorrectly() {
164180
connection.keyCommands().rename(KEY_1_BBUFFER, KEY_2_BBUFFER).as(StepVerifier::create).expectNext(true)
165181
.verifyComplete();
166182
assertThat(nativeCommands.exists(KEY_2)).isEqualTo(1L);
167-
assertThat(nativeCommands.exists(KEY_1)).isEqualTo(0L);
183+
assertThat(nativeCommands.exists(KEY_1)).isZero();
168184
}
169185

170186
@ParameterizedRedisTest // DATAREDIS-525
@@ -183,7 +199,7 @@ void renameNXShouldAlterKeyNameCorrectly() {
183199
.verifyComplete();
184200

185201
assertThat(nativeCommands.exists(KEY_2)).isEqualTo(1L);
186-
assertThat(nativeCommands.exists(KEY_1)).isEqualTo(0L);
202+
assertThat(nativeCommands.exists(KEY_1)).isZero();
187203
}
188204

189205
@ParameterizedRedisTest // DATAREDIS-525
@@ -395,7 +411,7 @@ void shouldMoveToDatabase() {
395411
.expectNext(true) //
396412
.expectComplete() //
397413
.verify();
398-
assertThat(nativeCommands.exists(KEY_1)).isEqualTo(0L);
414+
assertThat(nativeCommands.exists(KEY_1)).isZero();
399415
}
400416

401417
@ParameterizedRedisTest // DATAREDIS-694

src/test/java/org/springframework/data/redis/core/ReactiveRedisTemplateIntegrationTests.java

+21-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424

2525
import java.time.Duration;
2626
import java.time.Instant;
27-
import java.util.Collection;
28-
import java.util.Collections;
29-
import java.util.HashMap;
30-
import java.util.Map;
27+
import java.util.*;
3128
import java.util.function.Function;
3229

3330
import org.junit.jupiter.api.BeforeEach;
@@ -544,4 +541,24 @@ void listenToPatternLaterShouldReceiveChannelMessagesCorrectly() {
544541
.thenCancel() //
545542
.verify(Duration.ofSeconds(3));
546543
}
544+
545+
@ParameterizedRedisTest
546+
void countExistingKeysIfValidKeyExists() {
547+
548+
K key = keyFactory.instance();
549+
K key2 = keyFactory.instance();
550+
K key3 = keyFactory.instance();
551+
552+
redisTemplate.opsForValue().set(key, valueFactory.instance()).as(StepVerifier::create).expectNext(true).verifyComplete();
553+
redisTemplate.opsForValue().set(key2, valueFactory.instance()).as(StepVerifier::create).expectNext(true).verifyComplete();
554+
redisTemplate.opsForValue().set(key3, valueFactory.instance()).as(StepVerifier::create).expectNext(true).verifyComplete();
555+
556+
redisTemplate.countExistingKeys(Arrays.asList(key, key2, key3)).as(StepVerifier::create).expectNext(3L).verifyComplete();
557+
}
558+
559+
@ParameterizedRedisTest
560+
void countExistingKeysIfNotValidKeyExists() {
561+
K key = keyFactory.instance();
562+
redisTemplate.countExistingKeys(List.of(key)).as(StepVerifier::create).expectNext(0L).verifyComplete();
563+
}
547564
}

0 commit comments

Comments
 (0)