From b172c237e4e338c80fc4c71f1fc1c98b511b0645 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 14 Nov 2016 17:44:52 +0100 Subject: [PATCH] DATAREDIS-525 - Polishing. Enhance JavaDoc. Improve assertions. Reduce accepted collection-type boundary to Collection for commands that do not enforce a specific order. Add ByteUtil.getBytes(ByteBuffer) utility method. Reformat code. Extend documentation Fix parameter ambiguity in LettuceConnection.watch(). Original pull request: #229. --- pom.xml | 5 - src/main/asciidoc/new-features.adoc | 8 + .../redis/connection/ClusterSlotHashUtil.java | 7 +- .../redis/connection/ClusterTopology.java | 4 +- .../ReactiveClusterGeoCommands.java | 1 - .../ReactiveClusterHashCommands.java | 1 - .../ReactiveClusterHyperLogLogCommands.java | 1 - .../ReactiveClusterKeyCommands.java | 18 - .../ReactiveClusterListCommands.java | 1 - .../ReactiveClusterNumberCommands.java | 1 - .../ReactiveClusterSetCommands.java | 1 - .../ReactiveClusterStringCommands.java | 1 - .../ReactiveClusterZSetCommands.java | 1 - .../redis/connection/ReactiveGeoCommands.java | 543 +++++++++-- .../connection/ReactiveHashCommands.java | 236 ++++- .../ReactiveHyperLogLogCommands.java | 118 ++- .../redis/connection/ReactiveKeyCommands.java | 69 +- .../connection/ReactiveListCommands.java | 476 ++++++++-- .../connection/ReactiveNumberCommands.java | 150 +++- .../connection/ReactiveRedisConnection.java | 171 ++-- .../redis/connection/ReactiveSetCommands.java | 436 +++++++-- .../connection/ReactiveStringCommands.java | 536 +++++++---- .../connection/ReactiveZSetCommands.java | 845 ++++++++++++++---- .../redis/connection/RedisClusterNode.java | 2 +- .../connection/lettuce/LettuceConnection.java | 6 +- .../connection/lettuce/LettuceConverters.java | 3 +- .../LettuceReactiveClusterGeoCommands.java | 1 - .../LettuceReactiveClusterHashCommands.java | 1 - ...uceReactiveClusterHyperLogLogCommands.java | 15 +- .../LettuceReactiveClusterKeyCommands.java | 15 +- .../LettuceReactiveClusterListCommands.java | 14 +- .../LettuceReactiveClusterNumberCommands.java | 1 - .../LettuceReactiveClusterSetCommands.java | 61 +- .../LettuceReactiveClusterStringCommands.java | 7 +- .../LettuceReactiveClusterZSetCommands.java | 15 +- .../lettuce/LettuceReactiveKeyCommands.java | 4 +- .../lettuce/LettuceReactiveListCommands.java | 1 + .../LettuceReactiveNumberCommands.java | 3 +- ...LettuceReactiveRedisClusterConnection.java | 36 +- .../LettuceReactiveRedisConnection.java | 30 +- .../lettuce/LettuceReactiveSetCommands.java | 1 + .../LettuceReactiveStringCommands.java | 1 + .../lettuce/LettuceReactiveZSetCommands.java | 102 +-- .../data/redis/util/ByteUtils.java | 18 + .../LettuceReactiveHashCommandsTests.java | 12 +- .../LettuceReactiveSetCommandsTests.java | 2 +- 46 files changed, 3101 insertions(+), 880 deletions(-) diff --git a/pom.xml b/pom.xml index ddc3b5f38..9cc9bef7d 100644 --- a/pom.xml +++ b/pom.xml @@ -122,11 +122,6 @@ true - - io.reactivex - rxjava - 1.1.1 - diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 94b019f4c..5e02b6bb7 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -3,6 +3,14 @@ New and noteworthy in the latest releases. +[[new-in-2.0.0]] +== New in Spring Data Redis 2.0 + +* Upgrade to Java 8. +* Removed support for SRP and JRedis drivers. +* Upgrade to `Lettuce` 5.0. +* Reactive connection support using https://github.com/mp911de/lettuce[mp911de/lettuce] + [[new-in-1.8.0]] == New in Spring Data Redis 1.8 diff --git a/src/main/java/org/springframework/data/redis/connection/ClusterSlotHashUtil.java b/src/main/java/org/springframework/data/redis/connection/ClusterSlotHashUtil.java index cd8199daf..0d375d336 100644 --- a/src/main/java/org/springframework/data/redis/connection/ClusterSlotHashUtil.java +++ b/src/main/java/org/springframework/data/redis/connection/ClusterSlotHashUtil.java @@ -19,6 +19,7 @@ import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collection; +import org.springframework.data.redis.util.ByteUtils; import org.springframework.util.Assert; /** @@ -69,7 +70,10 @@ public final class ClusterSlotHashUtil { return true; } - return isSameSlotForAllKeys((byte[][]) keys.stream().map(ByteBuffer::array).toArray(size -> new byte[size][])); + return isSameSlotForAllKeys((byte[][]) keys.stream() // + .map(ByteBuffer::duplicate) // + .map(ByteUtils::getBytes) // + .toArray(byte[][]::new)); } /** @@ -164,5 +168,4 @@ public final class ClusterSlotHashUtil { } return crc & 0xFFFF; } - } diff --git a/src/main/java/org/springframework/data/redis/connection/ClusterTopology.java b/src/main/java/org/springframework/data/redis/connection/ClusterTopology.java index f37938642..b9d2a632f 100644 --- a/src/main/java/org/springframework/data/redis/connection/ClusterTopology.java +++ b/src/main/java/org/springframework/data/redis/connection/ClusterTopology.java @@ -168,7 +168,7 @@ public class ClusterTopology { */ public RedisClusterNode lookup(String nodeId) { - Assert.notNull(nodeId, "NodeId must not be null"); + Assert.notNull(nodeId, "NodeId must not be null!"); for (RedisClusterNode node : nodes) { if (nodeId.equals(node.getId())) { @@ -189,7 +189,7 @@ public class ClusterTopology { */ public RedisClusterNode lookup(RedisClusterNode node) { - Assert.notNull(node, "RedisClusterNode must not be null"); + Assert.notNull(node, "RedisClusterNode must not be null!"); if(nodes.contains(node) && StringUtils.hasText(node.getHost()) && StringUtils.hasText(node.getId())){ return node; diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterGeoCommands.java index b30b44940..3821d9d5a 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterGeoCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection; /** diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterHashCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterHashCommands.java index 2ee203a94..382ff2176 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterHashCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection; /** diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterHyperLogLogCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterHyperLogLogCommands.java index 290bf742c..d9e876240 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterHyperLogLogCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterHyperLogLogCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection; /** diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterKeyCommands.java index b933ab411..8ec8d5be1 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterKeyCommands.java @@ -13,23 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * Copyright 2016. the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package org.springframework.data.redis.connection; import java.nio.ByteBuffer; @@ -59,5 +42,4 @@ public interface ReactiveClusterKeyCommands extends ReactiveKeyCommands { * @return */ Mono randomKey(RedisClusterNode node); - } diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterListCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterListCommands.java index f5dbd4848..1beb312de 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterListCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection; /** diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterNumberCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterNumberCommands.java index e923a72d1..4004b0a0e 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterNumberCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterNumberCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection; /** diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterSetCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterSetCommands.java index 9aa35dd16..1c13c5b33 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterSetCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection; /** diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterStringCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterStringCommands.java index a36b119c3..3da9aa896 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterStringCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection; /** diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterZSetCommands.java index f3f4e147f..7ce705a43 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveClusterZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveClusterZSetCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection; /** diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveGeoCommands.java index 2e67557dc..c58e95c40 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveGeoCommands.java @@ -17,6 +17,7 @@ package org.springframework.data.redis.connection; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -27,6 +28,7 @@ import org.reactivestreams.Publisher; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.geo.Circle; import org.springframework.data.geo.Distance; +import org.springframework.data.geo.GeoResult; import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.Metric; import org.springframework.data.geo.Point; @@ -44,40 +46,72 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** + * Redis Geo commands executed using reactive infrastructure. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface ReactiveGeoCommands { /** + * {@code GEOADD} command parameters. + * * @author Christoph Strobl */ class GeoAddCommand extends KeyCommand { private final List> geoLocations; - public GeoAddCommand(ByteBuffer key, List> geoLocations) { + private GeoAddCommand(ByteBuffer key, List> geoLocations) { super(key); + this.geoLocations = geoLocations; } + /** + * Creates a new {@link GeoAddCommand} given {@link GeoLocation}. + * + * @param geoLocation must not be {@literal null}. + * @return a new {@link GeoAddCommand} for {@link GeoLocation}. + */ public static GeoAddCommand location(GeoLocation geoLocation) { + + Assert.notNull(geoLocation, "GeoLocation must not be null!"); + return new GeoAddCommand(null, Collections.singletonList(geoLocation)); } - public static GeoAddCommand locations(List> geoLocations) { + /** + * Creates a new {@link GeoAddCommand} given an {@literal index}. + * + * @param geoLocations must not be {@literal null}. + * @return a new {@link GeoAddCommand} for {@literal index}. + */ + public static GeoAddCommand locations(Collection> geoLocations) { + + Assert.notNull(geoLocations, "GeoLocations must not be null!"); + return new GeoAddCommand(null, new ArrayList<>(geoLocations)); } + /** + * Applies the Geo set {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link GeoAddCommand} with {@literal key} applied. + */ public GeoAddCommand to(ByteBuffer key) { return new GeoAddCommand(key, geoLocations); } + /** + * @return + */ public List> getGeoLocations() { return geoLocations; } - } /** @@ -90,9 +124,9 @@ public interface ReactiveGeoCommands { */ default Mono geoAdd(ByteBuffer key, Point point, ByteBuffer member) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(point, "point must not be null"); - Assert.notNull(member, "member must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(point, "Point must not be null!"); + Assert.notNull(member, "Member must not be null!"); return geoAdd(key, new GeoLocation<>(member, point)); } @@ -106,8 +140,8 @@ public interface ReactiveGeoCommands { */ default Mono geoAdd(ByteBuffer key, GeoLocation location) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(location, "location must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(location, "Location must not be null!"); return geoAdd(key, Collections.singletonList(location)); } @@ -119,10 +153,10 @@ public interface ReactiveGeoCommands { * @param locations must not be {@literal null}. * @return */ - default Mono geoAdd(ByteBuffer key, List> locations) { + default Mono geoAdd(ByteBuffer key, Collection> locations) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(locations, "locations must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(locations, "Locations must not be null!"); return geoAdd(Mono.just(GeoAddCommand.locations(locations).to(key))).next().map(NumericResponse::getOutput); } @@ -136,6 +170,8 @@ public interface ReactiveGeoCommands { Flux> geoAdd(Publisher commands); /** + * {@code GEODIST} command parameters. + * * @author Christoph Strobl */ class GeoDistCommand extends KeyCommand { @@ -145,7 +181,9 @@ public interface ReactiveGeoCommands { private final Metric metric; private GeoDistCommand(ByteBuffer key, ByteBuffer from, ByteBuffer to, Metric metric) { + super(key); + this.from = from; this.to = to; this.metric = metric; @@ -155,42 +193,99 @@ public interface ReactiveGeoCommands { return new GeoDistCommand(null, null, null, unit); } + /** + * Creates a new {@link GeoDistCommand} for {@link DistanceUnit#METERS}. + * + * @return a new {@link GeoDistCommand} for {@link DistanceUnit#METERS}. + */ public static GeoDistCommand meters() { return units(DistanceUnit.METERS); } - public static GeoDistCommand kiometers() { + /** + * Creates a new {@link GeoDistCommand} for {@link DistanceUnit#KILOMETERS}. + * + * @return a new {@link GeoDistCommand} for {@link DistanceUnit#KILOMETERS}. + */ + public static GeoDistCommand kilometers() { return units(DistanceUnit.KILOMETERS); } + /** + * Creates a new {@link GeoDistCommand} for {@link DistanceUnit#MILES}. + * + * @return a new {@link GeoDistCommand} for {@link DistanceUnit#MILES}. + */ public static GeoDistCommand miles() { return units(DistanceUnit.MILES); } + /** + * Creates a new {@link GeoDistCommand} for {@link DistanceUnit#FEET}. + * + * @return a new {@link GeoDistCommand} for {@link DistanceUnit#FEET}. + */ public static GeoDistCommand feet() { return units(DistanceUnit.FEET); } + /** + * Applies the {@literal from} member. Constructs a new command instance with all previously configured properties. + * + * @param from must not be {@literal null}. + * @return a new {@link GeoDistCommand} with {@literal from} applied. + */ public GeoDistCommand between(ByteBuffer from) { + + Assert.notNull(from, "From member must not be null!"); + return new GeoDistCommand(getKey(), from, to, metric); } + /** + * Applies the {@literal to} member. Constructs a new command instance with all previously configured properties. + * + * @param to must not be {@literal null}. + * @return a new {@link GeoDistCommand} with {@literal to} applied. + */ public GeoDistCommand and(ByteBuffer to) { + + Assert.notNull(to, "To member must not be null"); + return new GeoDistCommand(getKey(), from, to, metric); } + /** + * Applies the Geo set {@literal key} member. Constructs a new command instance with all previously configured + * properties. + * + * @param key must not be {@literal null}. + * @return a new {@link GeoDistCommand} with {@literal key} applied. + */ public GeoDistCommand forKey(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new GeoDistCommand(key, from, to, metric); } + /** + * @return + */ public ByteBuffer getFrom() { return from; } + /** + * @return + */ public ByteBuffer getTo() { return to; } + /** + * @return + */ public Optional getMetric() { return Optional.ofNullable(metric); } @@ -219,11 +314,12 @@ public interface ReactiveGeoCommands { */ default Mono geoDist(ByteBuffer key, ByteBuffer from, ByteBuffer to, Metric metric) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(from, "from must not be null"); - Assert.notNull(to, "to must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(from, "From must not be null!"); + Assert.notNull(to, "To must not be null!"); - return geoDist(Mono.just(GeoDistCommand.units(metric).between(from).and(to).forKey(key))).next() + return geoDist(Mono.just(GeoDistCommand.units(metric).between(from).and(to).forKey(key))) // + .next() // .map(CommandResponse::getOutput); } @@ -236,6 +332,8 @@ public interface ReactiveGeoCommands { Flux> geoDist(Publisher commands); /** + * {@code GEOHASH} command parameters. + * * @author Christoph Strobl */ class GeoHashCommand extends KeyCommand { @@ -245,21 +343,52 @@ public interface ReactiveGeoCommands { private GeoHashCommand(ByteBuffer key, List members) { super(key); + this.members = members; } + /** + * Creates a new {@link GeoHashCommand} given a {@literal member}. + * + * @param member must not be {@literal null}. + * @return a new {@link GeoHashCommand} for a {@literal member}. + */ public static GeoHashCommand member(ByteBuffer member) { + + Assert.notNull(member, "Member must not be null!"); + return new GeoHashCommand(null, Collections.singletonList(member)); } - public static GeoHashCommand members(List members) { + /** + * Creates a new {@link GeoHashCommand} given a {@link Collection} of values. + * + * @param members must not be {@literal null}. + * @return a new {@link GeoHashCommand} for a {@link Collection} of values. + */ + public static GeoHashCommand members(Collection members) { + + Assert.notNull(members, "Members must not be null!"); + return new GeoHashCommand(null, new ArrayList<>(members)); } + /** + * Applies the Geo set {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link GeoHashCommand} with {@literal key} applied. + */ public GeoHashCommand of(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new GeoHashCommand(key, members); } + /** + * @return + */ public List getMembers() { return members; } @@ -274,9 +403,10 @@ public interface ReactiveGeoCommands { */ default Mono geoHash(ByteBuffer key, ByteBuffer member) { - Assert.notNull(member, "member must not be null"); + Assert.notNull(member, "Member must not be null!"); - return geoHash(key, Collections.singletonList(member)).map(vals -> vals.isEmpty() ? null : vals.iterator().next()); + return geoHash(key, Collections.singletonList(member)) // + .map(vals -> vals.isEmpty() ? null : vals.iterator().next()); } /** @@ -286,12 +416,14 @@ public interface ReactiveGeoCommands { * @param members must not be {@literal null}. * @return */ - default Mono> geoHash(ByteBuffer key, List members) { + default Mono> geoHash(ByteBuffer key, Collection members) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(members, "members must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(members, "Members must not be null!"); - return geoHash(Mono.just(GeoHashCommand.members(members).of(key))).next().map(MultiValueResponse::getOutput); + return geoHash(Mono.just(GeoHashCommand.members(members).of(key))) // + .next() // + .map(MultiValueResponse::getOutput); } /** @@ -303,6 +435,8 @@ public interface ReactiveGeoCommands { Flux> geoHash(Publisher commands); /** + * {@code GEOPOS} command parameters. + * * @author Christoph Strobl */ class GeoPosCommand extends KeyCommand { @@ -312,21 +446,52 @@ public interface ReactiveGeoCommands { private GeoPosCommand(ByteBuffer key, List members) { super(key); + this.members = members; } + /** + * Creates a new {@link GeoPosCommand} given a {@literal member}. + * + * @param member must not be {@literal null}. + * @return a new {@link GeoPosCommand} for a {@literal member}. + */ public static GeoPosCommand member(ByteBuffer member) { + + Assert.notNull(member, "Member must not be null!"); + return new GeoPosCommand(null, Collections.singletonList(member)); } - public static GeoPosCommand members(List members) { + /** + * Creates a new {@link GeoPosCommand} given a {@link Collection} of values. + * + * @param members must not be {@literal null}. + * @return a new {@link GeoPosCommand} for a {@link Collection} of values. + */ + public static GeoPosCommand members(Collection members) { + + Assert.notNull(members, "Members must not be null!"); + return new GeoPosCommand(null, new ArrayList<>(members)); } + /** + * Applies the Geo set {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link GeoPosCommand} with {@literal key} applied. + */ public GeoPosCommand of(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new GeoPosCommand(key, members); } + /** + * @return + */ public List getMembers() { return members; } @@ -341,7 +506,7 @@ public interface ReactiveGeoCommands { */ default Mono geoPos(ByteBuffer key, ByteBuffer member) { - Assert.notNull(member, "member must not be null"); + Assert.notNull(member, "Member must not be null!"); return geoPos(key, Collections.singletonList(member)).map(vals -> vals.isEmpty() ? null : vals.iterator().next()); } @@ -353,10 +518,10 @@ public interface ReactiveGeoCommands { * @param members must not be {@literal null}. * @return */ - default Mono> geoPos(ByteBuffer key, List members) { + default Mono> geoPos(ByteBuffer key, Collection members) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(members, "members must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(members, "Members must not be null!"); return geoPos(Mono.just(GeoPosCommand.members(members).of(key))).next().map(MultiValueResponse::getOutput); } @@ -370,6 +535,8 @@ public interface ReactiveGeoCommands { Flux> geoPos(Publisher commands); /** + * {@code GEORADIUS} command parameters. + * * @author Christoph Strobl */ class GeoRadiusCommand extends KeyCommand { @@ -382,7 +549,9 @@ public interface ReactiveGeoCommands { private GeoRadiusCommand(ByteBuffer key, Point point, Distance distance, GeoRadiusCommandArgs args, ByteBuffer store, ByteBuffer storeDist) { + super(key); + this.distance = distance; this.point = point; this.args = args == null ? GeoRadiusCommandArgs.newGeoRadiusArgs() : args; @@ -390,81 +559,190 @@ public interface ReactiveGeoCommands { this.storeDist = storeDist; } + /** + * Creates a new {@link GeoRadiusCommand} given a {@link Distance}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} for a {@link Distance}. + */ public static GeoRadiusCommand within(Distance distance) { + + Assert.notNull(distance, "Distance must not be null!"); + return new GeoRadiusCommand(null, null, distance, null, null, null); } - public static GeoRadiusCommand withinMeters(Double distance) { + /** + * Creates a new {@link GeoRadiusCommand} given a {@literal distance} in {@link DistanceUnit#METERS}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} for a {@literal distance} in {@link DistanceUnit#METERS}. + */ + public static GeoRadiusCommand withinMeters(double distance) { return within(new Distance(distance, DistanceUnit.METERS)); } - public static GeoRadiusCommand withinKiometers(Double distance) { + /** + * Creates a new {@link GeoRadiusCommand} given a {@literal distance} in {@link DistanceUnit#KILOMETERS}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} for a {@literal distance} in {@link DistanceUnit#KILOMETERS}. + */ + public static GeoRadiusCommand withinKilometers(double distance) { return within(new Distance(distance, DistanceUnit.KILOMETERS)); } - public static GeoRadiusCommand withinMiles(Double distance) { + /** + * Creates a new {@link GeoRadiusCommand} given a {@literal distance} in {@link DistanceUnit#MILES}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} for a {@literal distance} in {@link DistanceUnit#MILES}. + */ + public static GeoRadiusCommand withinMiles(double distance) { return within(new Distance(distance, DistanceUnit.MILES)); } - public static GeoRadiusCommand withinFeet(Double distance) { + /** + * Creates a new {@link GeoRadiusCommand} given a {@literal distance} in {@link DistanceUnit#FEET}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} for a {@literal distance} in {@link DistanceUnit#FEET}. + */ + public static GeoRadiusCommand withinFeet(double distance) { return within(new Distance(distance, DistanceUnit.FEET)); } + /** + * Creates a new {@link GeoRadiusCommand} given a {@link Circle}. + * + * @param circle must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} for a {@link Circle}. + */ public static GeoRadiusCommand within(Circle circle) { + + Assert.notNull(circle, "Circle must not be null!"); + return within(circle.getRadius()).from(circle.getCenter()); } + /** + * Sets the {@literal center} {@link Point}. Constructs a new command instance with all previously configured + * properties. + * + * @param center must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} with {@link Point} applied. + */ public GeoRadiusCommand from(Point center) { + + Assert.notNull(center, "Center point must not be null!"); + return new GeoRadiusCommand(getKey(), center, distance, args, store, storeDist); } + /** + * Applies command {@link Flag flags}. Constructs a new command instance with all previously configured properties. + * + * @param flag must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} with {@link Flag} applied. + */ public GeoRadiusCommand withFlag(Flag flag) { + Assert.notNull(flag, "Flag must not be null!"); + GeoRadiusCommandArgs args = cloneArgs(); args.flags.add(flag); return new GeoRadiusCommand(getKey(), point, distance, args, store, storeDist); } + /** + * Enables coordinate retrieval. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link GeoRadiusCommand} with {@link Flag#WITHCOORD} applied. + */ public GeoRadiusCommand withCoord() { return withFlag(Flag.WITHCOORD); } + /** + * Enables distance retrieval. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link GeoRadiusCommand} with {@link Flag#WITHDIST} applied. + */ public GeoRadiusCommand withDist() { return withFlag(Flag.WITHDIST); } + /** + * Applies command {@link GeoRadiusCommandArgs}. Constructs a new command instance with all previously configured + * properties. + * + * @param args can be {@literal null}. + * @return a new {@link GeoRadiusCommand} with {@link GeoRadiusCommandArgs} applied. + */ public GeoRadiusCommand withArgs(GeoRadiusCommandArgs args) { return new GeoRadiusCommand(getKey(), point, distance, args, store, storeDist); } - public GeoRadiusCommand limitTo(Long limit) { + /** + * Applies the {@literal limit}. Constructs a new command instance with all previously configured properties. + * + * @param limit + * @return a new {@link GeoRadiusCommand} with {@literal limit} applied. + */ + public GeoRadiusCommand limitTo(long limit) { GeoRadiusCommandArgs args = cloneArgs(); - if (limit != null) { - args = args.limit(limit); - } + args = args.limit(limit); return new GeoRadiusCommand(getKey(), point, distance, args, store, storeDist); } + /** + * Applies the distance sort {@link Direction}. Constructs a new command instance with all previously configured + * properties. + * + * @param direction must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} with sort {@link Direction} applied. + */ public GeoRadiusCommand sort(Direction direction) { + Assert.notNull(direction, "Direction must not be null!"); + GeoRadiusCommandArgs args = cloneArgs(); args.sortDirection = direction; return new GeoRadiusCommand(getKey(), point, distance, args, store, storeDist); } + /** + * Applies ascending sort by distance. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link GeoRadiusCommand} with sort {@link Direction#ASC} applied. + */ public GeoRadiusCommand orderByDistanceAsc() { return sort(Direction.ASC); } + /** + * Applies descending sort by distance. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link GeoRadiusCommand} with sort {@link Direction#DESC} applied. + */ public GeoRadiusCommand orderByDistanceDesc() { return sort(Direction.DESC); } + /** + * Applies the Geo set {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link GeoRadiusCommand} with {@literal key} applied. + */ public GeoRadiusCommand forKey(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new GeoRadiusCommand(key, point, distance, args, store, storeDist); } @@ -488,34 +766,58 @@ public interface ReactiveGeoCommands { return new GeoRadiusCommand(getKey(), point, distance, args, store, key); } + /** + * @return + */ public Optional getDirection() { return Optional.ofNullable(args.getSortDirection()); } + /** + * @return + */ public Distance getDistance() { return distance; } + /** + * @return + */ public Set getFlags() { return args.getFlags(); } + /** + * @return + */ public Optional getLimit() { return Optional.ofNullable(args.getLimit()); } + /** + * @return + */ public Point getPoint() { return point; } + /** + * @return + */ public Optional getStore() { return Optional.ofNullable(store); } + /** + * @return + */ public Optional getStoreDist() { return Optional.ofNullable(storeDist); } + /** + * @return + */ public Optional getArgs() { return Optional.ofNullable(args); } @@ -539,7 +841,7 @@ public interface ReactiveGeoCommands { */ default Mono>> geoRadius(ByteBuffer key, Circle circle) { return geoRadius(key, circle, null) - .map(res -> res.getContent().stream().map(val -> val.getContent()).collect(Collectors.toList())); + .map(res -> res.getContent().stream().map(GeoResult::getContent).collect(Collectors.toList())); } /** @@ -553,8 +855,8 @@ public interface ReactiveGeoCommands { default Mono>> geoRadius(ByteBuffer key, Circle circle, GeoRadiusCommandArgs geoRadiusArgs) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(circle, "circle must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(circle, "Circle must not be null!"); return geoRadius(Mono.just(GeoRadiusCommand.within(circle).withArgs(geoRadiusArgs).forKey(key))).next() .map(CommandResponse::getOutput); @@ -570,6 +872,8 @@ public interface ReactiveGeoCommands { Publisher commands); /** + * {@code GEORADIUSBYMEMBER} command parameters. + * * @author Christoph Strobl */ class GeoRadiusByMemberCommand extends KeyCommand { @@ -584,6 +888,7 @@ public interface ReactiveGeoCommands { ByteBuffer store, ByteBuffer storeDist) { super(key); + this.distance = distance; this.member = member; this.args = args == null ? GeoRadiusCommandArgs.newGeoRadiusArgs() : args; @@ -591,76 +896,173 @@ public interface ReactiveGeoCommands { this.storeDist = storeDist; } + /** + * Creates a new {@link GeoRadiusByMemberCommand} given a {@link Distance}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} for a {@link Distance}. + */ public static GeoRadiusByMemberCommand within(Distance distance) { + + Assert.notNull(distance, "Distance must not be null!"); + return new GeoRadiusByMemberCommand(null, null, distance, GeoRadiusCommandArgs.newGeoRadiusArgs(), null, null); } - public static GeoRadiusByMemberCommand withinMeters(Double distance) { + /** + * Creates a new {@link GeoRadiusByMemberCommand} given a {@literal distance} in {@link DistanceUnit#METERS}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} for a {@literal distance} in {@link DistanceUnit#METERS}. + */ + public static GeoRadiusByMemberCommand withinMeters(double distance) { return within(new Distance(distance, DistanceUnit.METERS)); } - public static GeoRadiusByMemberCommand withinKiometers(Double distance) { + /** + * Creates a new {@link GeoRadiusByMemberCommand} given a {@literal distance} in {@link DistanceUnit#KILOMETERS}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} for a {@literal distance} in {@link DistanceUnit#KILOMETERS}. + */ + public static GeoRadiusByMemberCommand withinKiometers(double distance) { return within(new Distance(distance, DistanceUnit.KILOMETERS)); } - public static GeoRadiusByMemberCommand withinMiles(Double distance) { + /** + * Creates a new {@link GeoRadiusByMemberCommand} given a {@literal distance} in {@link DistanceUnit#MILES}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} for a {@literal distance} in {@link DistanceUnit#MILES}. + */ + public static GeoRadiusByMemberCommand withinMiles(double distance) { return within(new Distance(distance, DistanceUnit.MILES)); } - public static GeoRadiusByMemberCommand withinFeet(Double distance) { + /** + * Creates a new {@link GeoRadiusByMemberCommand} given a {@literal distance} in {@link DistanceUnit#FEET}. + * + * @param distance must not be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} for a {@literal distance} in {@link DistanceUnit#FEET}. + */ + public static GeoRadiusByMemberCommand withinFeet(double distance) { return within(new Distance(distance, DistanceUnit.FEET)); } + /** + * Sets the {@literal member}. Constructs a new command instance with all previously configured properties. + * + * @param member must not be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} with {@literal member} applied. + */ public GeoRadiusByMemberCommand from(ByteBuffer member) { + + Assert.notNull(member, "Member must not be null!"); + return new GeoRadiusByMemberCommand(getKey(), member, distance, args, store, storeDist); } - public GeoRadiusByMemberCommand withArgs(GeoRadiusCommandArgs args) { - return new GeoRadiusByMemberCommand(getKey(), member, distance, args, store, storeDist); - } - + /** + * Applies command {@link Flag flags}. Constructs a new command instance with all previously configured properties. + * + * @param flag must not be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} with {@literal key} applied. + */ public GeoRadiusByMemberCommand withFlag(Flag flag) { + Assert.notNull(flag, "Flag must not be null!"); + GeoRadiusCommandArgs args = cloneArgs(); args.flags.add(flag); return new GeoRadiusByMemberCommand(getKey(), member, distance, args, store, storeDist); } + /** + * Enables coordinate retrieval. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link GeoRadiusByMemberCommand} with {@link Flag#WITHCOORD} applied. + */ public GeoRadiusByMemberCommand withCoord() { return withFlag(Flag.WITHCOORD); } + /** + * Enables distance retrieval. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link GeoRadiusByMemberCommand} with {@link Flag#WITHDIST} applied. + */ public GeoRadiusByMemberCommand withDist() { return withFlag(Flag.WITHDIST); } - public GeoRadiusByMemberCommand limitTo(Long limit) { - - GeoRadiusCommandArgs args = cloneArgs(); - if (limit != null) { - args = args.limit(limit); - } + /** + * Applies command {@link GeoRadiusCommandArgs}. Constructs a new command instance with all previously configured + * properties. + * + * @param args can be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} with {@link GeoRadiusCommandArgs} applied. + */ + public GeoRadiusByMemberCommand withArgs(GeoRadiusCommandArgs args) { return new GeoRadiusByMemberCommand(getKey(), member, distance, args, store, storeDist); } + /** + * Applies the {@literal limit}. Constructs a new command instance with all previously configured properties. + * + * @param limit + * @return a new {@link GeoRadiusByMemberCommand} with {@literal limit} applied. + */ + public GeoRadiusByMemberCommand limitTo(long limit) { + + GeoRadiusCommandArgs args = cloneArgs(); + args.limit(limit); + + return new GeoRadiusByMemberCommand(getKey(), member, distance, args, store, storeDist); + } + + /** + * Applies the distance sort {@link Direction}. Constructs a new command instance with all previously configured + * properties. + * + * @param direction must not be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} with sort {@link Direction} applied. + */ public GeoRadiusByMemberCommand sort(Direction direction) { + Assert.notNull(direction, "Direction must not be null!"); + GeoRadiusCommandArgs args = cloneArgs(); args.sortDirection = direction; return new GeoRadiusByMemberCommand(getKey(), member, distance, args, store, storeDist); } + /** + * Applies ascending sort by distance. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link GeoRadiusByMemberCommand} with sort {@link Direction#ASC} applied. + */ public GeoRadiusByMemberCommand orderByDistanceAsc() { return sort(Direction.ASC); } + /** + * Applies descending sort by distance. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link GeoRadiusByMemberCommand} with sort {@link Direction#DESC} applied. + */ public GeoRadiusByMemberCommand orderByDistanceDesc() { return sort(Direction.DESC); } + /** + * Applies the Geo set {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link GeoRadiusByMemberCommand} with {@literal key} applied. + */ public GeoRadiusByMemberCommand forKey(ByteBuffer key) { return new GeoRadiusByMemberCommand(key, member, distance, args, store, storeDist); } @@ -685,34 +1087,58 @@ public interface ReactiveGeoCommands { return new GeoRadiusByMemberCommand(getKey(), member, distance, args, store, key); } + /** + * @return + */ public Optional getDirection() { return Optional.ofNullable(args.getSortDirection()); } + /** + * @return + */ public Distance getDistance() { return distance; } + /** + * @return + */ public Set getFlags() { return args.getFlags(); } + /** + * @return + */ public Optional getLimit() { return Optional.ofNullable(args.getLimit()); } + /** + * @return + */ public ByteBuffer getMember() { return member; } + /** + * @return + */ public Optional getStore() { return Optional.ofNullable(store); } + /** + * @return + */ public Optional getStoreDist() { return Optional.ofNullable(storeDist); } + /** + * @return + */ public Optional getArgs() { return Optional.ofNullable(args); } @@ -725,7 +1151,6 @@ public interface ReactiveGeoCommands { return args.clone(); } - } /** @@ -737,7 +1162,7 @@ public interface ReactiveGeoCommands { */ default Mono>> geoRadiusByMember(ByteBuffer key, ByteBuffer member, Distance distance) { return geoRadiusByMember(key, member, distance, null) - .map(res -> res.getContent().stream().map(val -> val.getContent()).collect(Collectors.toList())); + .map(res -> res.getContent().stream().map(GeoResult::getContent).collect(Collectors.toList())); } /** @@ -751,9 +1176,9 @@ public interface ReactiveGeoCommands { default Mono>> geoRadiusByMember(ByteBuffer key, ByteBuffer member, Distance distance, GeoRadiusCommandArgs geoRadiusArgs) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(member, "member must not be null"); - Assert.notNull(distance, "distance must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(member, "Member must not be null!"); + Assert.notNull(distance, "Distance must not be null!"); return geoRadiusByMember( Mono.just(GeoRadiusByMemberCommand.within(distance).from(member).forKey(key).withArgs(geoRadiusArgs))).next() @@ -763,7 +1188,7 @@ public interface ReactiveGeoCommands { /** * Get the {@literal member}s within given {@link Distance} from {@literal member} applying given parameters. * - * @param commands + * @param commands must not be {@literal null}. * @return */ Flux>>> geoRadiusByMember( diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveHashCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveHashCommands.java index 47969e569..988e6db6d 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveHashCommands.java @@ -17,6 +17,7 @@ package org.springframework.data.redis.connection; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -24,6 +25,7 @@ import java.util.Map; import org.reactivestreams.Publisher; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.connection.ReactiveRedisConnection.BooleanResponse; +import org.springframework.data.redis.connection.ReactiveRedisConnection.Command; import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand; import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiValueResponse; @@ -34,63 +36,115 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** + * Redis Hash commands executed using reactive infrastructure. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface ReactiveHashCommands { /** + * {@literal HSET} {@link Command}. + * * @author Christoph Strobl */ class HSetCommand extends KeyCommand { private static final ByteBuffer SINGLE_VALUE_KEY = ByteBuffer.allocate(0); private final Map fieldValueMap; - private final Boolean upsert; + private final boolean upsert; - private HSetCommand(ByteBuffer key, Map keyValueMap, Boolean upsert) { + private HSetCommand(ByteBuffer key, Map keyValueMap, boolean upsert) { super(key); + this.fieldValueMap = keyValueMap; this.upsert = upsert; } + /** + * Creates a new {@link HSetCommand} given a {@link ByteBuffer key}. + * + * @param value must not be {@literal null}. + * @return a new {@link HSetCommand} for {@link ByteBuffer key}. + */ public static HSetCommand value(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new HSetCommand(null, Collections.singletonMap(SINGLE_VALUE_KEY, value), Boolean.TRUE); } + /** + * Creates a new {@link HSetCommand} given a {@link Map} of field values. + * + * @param fieldValueMap must not be {@literal null}. + * @return a new {@link HSetCommand} for a {@link Map} of field values. + */ public static HSetCommand fieldValues(Map fieldValueMap) { + + Assert.notNull(fieldValueMap, "Field values map must not be null!"); + return new HSetCommand(null, fieldValueMap, Boolean.TRUE); } + /** + * Applies a field. Constructs a new command instance with all previously configured properties. + * + * @param field must not be {@literal null}. + * @return a new {@link HSetCommand} with {@literal field} applied. + */ public HSetCommand ofField(ByteBuffer field) { if (!fieldValueMap.containsKey(SINGLE_VALUE_KEY)) { throw new InvalidDataAccessApiUsageException("Value has not been set."); } + Assert.notNull(field, "Field not be null!"); + return new HSetCommand(getKey(), Collections.singletonMap(field, fieldValueMap.get(SINGLE_VALUE_KEY)), upsert); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link HSetCommand} with {@literal key} applied. + */ public HSetCommand forKey(ByteBuffer key) { + + Assert.notNull(key, "Key not be null!"); + return new HSetCommand(key, fieldValueMap, upsert); } + /** + * Disable upsert. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link HSetCommand} with upsert disabled. + */ public HSetCommand ifValueNotExists() { return new HSetCommand(getKey(), fieldValueMap, Boolean.FALSE); } - public Boolean isUpsert() { + /** + * @return + */ + public boolean isUpsert() { return upsert; } + /** + * @return + */ public Map getFieldValueMap() { return fieldValueMap; } } /** - * Set the {@code value} of a hash {@code field}. + * Set the {@literal value} of a hash {@literal field}. * * @param key must not be {@literal null}. * @param field must not be {@literal null}. @@ -99,15 +153,15 @@ public interface ReactiveHashCommands { */ default Mono hSet(ByteBuffer key, ByteBuffer field, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(field, "field must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(field, "Field must not be null!"); + Assert.notNull(value, "Value must not be null!"); return hSet(Mono.just(HSetCommand.value(value).ofField(field).forKey(key))).next().map(BooleanResponse::getOutput); } /** - * Set the {@code value} of a hash {@code field}. + * Set the {@literal value} of a hash {@literal field}. * * @param key must not be {@literal null}. * @param field must not be {@literal null}. @@ -116,16 +170,16 @@ public interface ReactiveHashCommands { */ default Mono hSetNX(ByteBuffer key, ByteBuffer field, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(field, "field must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(field, "Field must not be null!"); + Assert.notNull(value, "Value must not be null!"); return hSet(Mono.just(HSetCommand.value(value).ofField(field).forKey(key).ifValueNotExists())).next() .map(BooleanResponse::getOutput); } /** - * Set multiple hash fields to multiple values using data provided in {@code fieldValueMap}. + * Set multiple hash fields to multiple values using data provided in {@literal fieldValueMap}. * * @param key must not be {@literal null}. * @param fieldValueMap must not be {@literal null}. @@ -133,15 +187,15 @@ public interface ReactiveHashCommands { */ default Mono hMSet(ByteBuffer key, Map fieldValueMap) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(fieldValueMap, "field must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(fieldValueMap, "Field must not be null!"); return hSet(Mono.just(HSetCommand.fieldValues(fieldValueMap).forKey(key).ifValueNotExists())).next() .map(BooleanResponse::getOutput); } /** - * Set the {@code value} of a hash {@code field}. + * Set the {@literal value} of a hash {@literal field}. * * @param commands must not be {@literal null}. * @return @@ -149,6 +203,8 @@ public interface ReactiveHashCommands { Flux> hSet(Publisher commands); /** + * {@literal HGET} {@link Command}. + * * @author Christoph Strobl */ class HGetCommand extends KeyCommand { @@ -158,28 +214,59 @@ public interface ReactiveHashCommands { private HGetCommand(ByteBuffer key, List fields) { super(key); + this.fields = fields; } + /** + * Creates a new {@link HGetCommand} given a {@link ByteBuffer field name}. + * + * @param field must not be {@literal null}. + * @return a new {@link HGetCommand} for a {@link ByteBuffer field name}. + */ public static HGetCommand field(ByteBuffer field) { + + Assert.notNull(field, "Field must not be null!"); + return new HGetCommand(null, Collections.singletonList(field)); } - public static HGetCommand fields(List fields) { + /** + * Creates a new {@link HGetCommand} given a {@link Collection} of field names. + * + * @param fields must not be {@literal null}. + * @return a new {@link HGetCommand} for a {@link Collection} of field names. + */ + public static HGetCommand fields(Collection fields) { + + Assert.notNull(fields, "Fields must not be null!"); + return new HGetCommand(null, new ArrayList<>(fields)); } + /** + * Applies the hash {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link HGetCommand} with {@literal key} applied. + */ public HGetCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new HGetCommand(key, fields); } + /** + * @return + */ public List getFields() { return fields; } } /** - * Get value for given {@code field} from hash at {@code key}. + * Get value for given {@literal field} from hash at {@literal key}. * * @param key must not be {@literal null}. * @param field must not be {@literal null}. @@ -190,22 +277,22 @@ public interface ReactiveHashCommands { } /** - * Get values for given {@code fields} from hash at {@code key}. + * Get values for given {@literal fields} from hash at {@literal key}. * * @param key must not be {@literal null}. * @param fields must not be {@literal null}. * @return */ - default Mono> hMGet(ByteBuffer key, List fields) { + default Mono> hMGet(ByteBuffer key, Collection fields) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(fields, "fields must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(fields, "Fields must not be null!"); return hMGet(Mono.just(HGetCommand.fields(fields).from(key))).next().map(MultiValueResponse::getOutput); } /** - * Get values for given {@code fields} from hash at {@code key}. + * Get values for given {@literal fields} from hash at {@literal key}. * * @param commands must not be {@literal null}. * @return @@ -213,6 +300,8 @@ public interface ReactiveHashCommands { Flux> hMGet(Publisher commands); /** + * {@literal HEXISTS} {@link Command}. + * * @author Christoph Strobl */ class HExistsCommand extends KeyCommand { @@ -222,24 +311,46 @@ public interface ReactiveHashCommands { private HExistsCommand(ByteBuffer key, ByteBuffer field) { super(key); + this.field = field; } + /** + * Creates a new {@link HExistsCommand} given a {@link ByteBuffer field name}. + * + * @param field must not be {@literal null}. + * @return a new {@link HExistsCommand} for a {@link ByteBuffer field name}. + */ public static HExistsCommand field(ByteBuffer field) { + + Assert.notNull(field, "Field must not be null!"); + return new HExistsCommand(null, field); } + /** + * Applies the hash {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link HExistsCommand} with {@literal key} applied. + */ public HExistsCommand in(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new HExistsCommand(key, field); } + /** + * @return + */ public ByteBuffer getField() { return field; } } /** - * Determine if given hash {@code field} exists. + * Determine if given hash {@literal field} exists. * * @param key must not be {@literal null}. * @param field must not be {@literal null}. @@ -247,14 +358,14 @@ public interface ReactiveHashCommands { */ default Mono hExists(ByteBuffer key, ByteBuffer field) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(field, "field must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(field, "Field must not be null!"); return hExists(Mono.just(HExistsCommand.field(field).in(key))).next().map(BooleanResponse::getOutput); } /** - * Determine if given hash {@code field} exists. + * Determine if given hash {@literal field} exists. * * @param commands * @return @@ -269,29 +380,61 @@ public interface ReactiveHashCommands { private final List fields; private HDelCommand(ByteBuffer key, List fields) { + super(key); + this.fields = fields; } + /** + * Creates a new {@link HDelCommand} given a {@link ByteBuffer field name}. + * + * @param field must not be {@literal null}. + * @return a new {@link HDelCommand} for a {@link ByteBuffer field name}. + */ public static HDelCommand field(ByteBuffer field) { + + Assert.notNull(field, "Field must not be null!"); + return new HDelCommand(null, Collections.singletonList(field)); } - public static HDelCommand fields(List fields) { + /** + * Creates a new {@link HDelCommand} given a {@link Collection} of field names. + * + * @param fields must not be {@literal null}. + * @return a new {@link HDelCommand} for a {@link Collection} of field names. + */ + public static HDelCommand fields(Collection fields) { + + Assert.notNull(fields, "Fields must not be null!"); + return new HDelCommand(null, new ArrayList<>(fields)); } + /** + * Applies the hash {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link HDelCommand} with {@literal key} applied. + */ public HDelCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new HDelCommand(key, fields); } + /** + * @return + */ public List getFields() { return fields; } } /** - * Delete given hash {@code field}. + * Delete given hash {@literal field}. * * @param key must not be {@literal null}. * @param field must not be {@literal null}. @@ -299,28 +442,28 @@ public interface ReactiveHashCommands { */ default Mono hDel(ByteBuffer key, ByteBuffer field) { - Assert.notNull(field, "field must not be null"); + Assert.notNull(field, "Field must not be null!"); return hDel(key, Collections.singletonList(field)).map(val -> val > 0 ? Boolean.TRUE : Boolean.FALSE); } /** - * Delete given hash {@code fields}. + * Delete given hash {@literal fields}. * * @param key must not be {@literal null}. * @param fields must not be {@literal null}. * @return */ - default Mono hDel(ByteBuffer key, List fields) { + default Mono hDel(ByteBuffer key, Collection fields) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(fields, "fields must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(fields, "Fields must not be null!"); return hDel(Mono.just(HDelCommand.fields(fields).from(key))).next().map(NumericResponse::getOutput); } /** - * Delete given hash {@code fields}. + * Delete given hash {@literal fields}. * * @param commands must not be {@literal null}. * @return @@ -328,20 +471,20 @@ public interface ReactiveHashCommands { Flux> hDel(Publisher commands); /** - * Get size of hash at {@code key}. + * Get size of hash at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono hLen(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return hLen(Mono.just(new KeyCommand(key))).next().map(NumericResponse::getOutput); } /** - * Get size of hash at {@code key}. + * Get size of hash at {@literal key}. * * @param commands must not be {@literal null}. * @return @@ -349,20 +492,20 @@ public interface ReactiveHashCommands { Flux> hLen(Publisher commands); /** - * Get key set (fields) of hash at {@code key}. + * Get key set (fields) of hash at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono> hKeys(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return hKeys(Mono.just(new KeyCommand(key))).next().map(MultiValueResponse::getOutput); } /** - * Get key set (fields) of hash at {@code key}. + * Get key set (fields) of hash at {@literal key}. * * @param commands must not be {@literal null}. * @return @@ -370,20 +513,20 @@ public interface ReactiveHashCommands { Flux> hKeys(Publisher commands); /** - * Get entry set (values) of hash at {@code key}. + * Get entry set (values) of hash at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono> hVals(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return hVals(Mono.just(new KeyCommand(key))).next().map(MultiValueResponse::getOutput); } /** - * Get entry set (values) of hash at {@code key}. + * Get entry set (values) of hash at {@literal key}. * * @param commands must not be {@literal null}. * @return @@ -391,24 +534,23 @@ public interface ReactiveHashCommands { Flux> hVals(Publisher commands); /** - * Get entire hash stored at {@code key}. + * Get entire hash stored at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono> hGetAll(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return hGetAll(Mono.just(new KeyCommand(key))).next().map(CommandResponse::getOutput); } /** - * Get entire hash stored at {@code key}. + * Get entire hash stored at {@literal key}. * * @param commands must not be {@literal null}. * @return */ Flux>> hGetAll(Publisher commands); - } diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveHyperLogLogCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveHyperLogLogCommands.java index b93bee6b5..54c04f454 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveHyperLogLogCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveHyperLogLogCommands.java @@ -17,6 +17,7 @@ package org.springframework.data.redis.connection; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -31,12 +32,17 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** + * Redis HyperLogLog commands executed using reactive infrastructure. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface ReactiveHyperLogLogCommands { /** + * {@code PFADD} command parameters. + * * @author Christoph Strobl */ class PfAddCommand extends KeyCommand { @@ -49,18 +55,48 @@ public interface ReactiveHyperLogLogCommands { this.values = values; } + /** + * Creates a new {@link PfAddCommand} given a {@link ByteBuffer value}. + * + * @param value must not be {@literal null}. + * @return a new {@link PfAddCommand} for {@link ByteBuffer value}. + */ public static PfAddCommand value(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return values(Collections.singletonList(value)); } - public static PfAddCommand values(List values) { + /** + * Creates a new {@link PfAddCommand} given a {@link Collection} of {@link ByteBuffer values}. + * + * @param values must not be {@literal null}. + * @return a new {@link PfAddCommand} for {@link ByteBuffer key}. + */ + public static PfAddCommand values(Collection values) { + + Assert.notNull(values, "Values must not be null!"); + return new PfAddCommand(null, new ArrayList<>(values)); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link PfAddCommand} with {@literal key} applied. + */ public PfAddCommand to(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new PfAddCommand(key, values); } + /** + * @return + */ public List getValues() { return values; } @@ -75,7 +111,7 @@ public interface ReactiveHyperLogLogCommands { */ default Mono pfAdd(ByteBuffer key, ByteBuffer value) { - Assert.notNull(value, "value must not be null"); + Assert.notNull(value, "Value must not be null!"); return pfAdd(key, Collections.singletonList(value)); } @@ -87,10 +123,10 @@ public interface ReactiveHyperLogLogCommands { * @param values must not be {@literal null}. * @return */ - default Mono pfAdd(ByteBuffer key, List values) { + default Mono pfAdd(ByteBuffer key, Collection values) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(values, "values must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(values, "Values must not be null!"); return pfAdd(Mono.just(PfAddCommand.values(values).to(key))).next().map(NumericResponse::getOutput); } @@ -104,6 +140,8 @@ public interface ReactiveHyperLogLogCommands { Flux> pfAdd(Publisher commands); /** + * {@code PFCOUNT} command parameters. + * * @author Christoph Strobl */ class PfCountCommand implements Command { @@ -116,23 +154,46 @@ public interface ReactiveHyperLogLogCommands { this.keys = keys; } + /** + * Creates a new {@link PfCountCommand} given a {@link ByteBuffer key}. + * + * @param key must not be {@literal null}. + * @return a new {@link PfCountCommand} for {@link ByteBuffer key}. + */ public static PfCountCommand valueIn(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return valuesIn(Collections.singletonList(key)); } - public static PfCountCommand valuesIn(List keys) { - return new PfCountCommand(keys); + /** + * Creates a new {@link PfCountCommand} given a {@link Collection} of {@literal keys}. + * + * @param keys must not be {@literal null}. + * @return a new {@link PfCountCommand} for {@literal keys}. + */ + public static PfCountCommand valuesIn(Collection keys) { + + Assert.notNull(keys, "Keys must not be null!"); + + return new PfCountCommand(new ArrayList<>(keys)); } + /** + * @return + */ public List getKeys() { return keys; } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() + */ @Override public ByteBuffer getKey() { return null; } - } /** @@ -143,7 +204,7 @@ public interface ReactiveHyperLogLogCommands { */ default Mono pfCount(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return pfCount(Collections.singletonList(key)); } @@ -154,9 +215,9 @@ public interface ReactiveHyperLogLogCommands { * @param keys must not be {@literal null}. * @return */ - default Mono pfCount(List keys) { + default Mono pfCount(Collection keys) { - Assert.notNull(keys, "keys must not be null"); + Assert.notNull(keys, "Keys must not be null!"); return pfCount(Mono.just(PfCountCommand.valuesIn(keys))).next().map(NumericResponse::getOutput); } @@ -170,6 +231,8 @@ public interface ReactiveHyperLogLogCommands { Flux> pfCount(Publisher commands); /** + * {@code PFMERGE} command parameters. + * * @author Christoph Strobl */ class PfMergeCommand extends KeyCommand { @@ -182,14 +245,36 @@ public interface ReactiveHyperLogLogCommands { this.sourceKeys = sourceKeys; } - public static PfMergeCommand valuesIn(List sourceKeys) { - return new PfMergeCommand(null, sourceKeys); + /** + * Creates a new {@link PfMergeCommand} given a {@link Collection} of {@literal sourceKeys}. + * + * @param sourceKeys must not be {@literal null}. + * @return a new {@link PfMergeCommand} for {@literal sourceKeys}. + */ + public static PfMergeCommand valuesIn(Collection sourceKeys) { + + Assert.notNull(sourceKeys, "Source keys must not be null!"); + + return new PfMergeCommand(null, new ArrayList<>(sourceKeys)); } + /** + * Applies the {@literal destinationKey}. Constructs a new command instance with all previously configured + * properties. + * + * @param destinationKey must not be {@literal null}. + * @return a new {@link PfMergeCommand} with {@literal destinationKey} applied. + */ public PfMergeCommand into(ByteBuffer destinationKey) { + + Assert.notNull(destinationKey, "Destination key must not be null!"); + return new PfMergeCommand(destinationKey, sourceKeys); } + /** + * @return + */ public List getSourceKeys() { return sourceKeys; } @@ -202,10 +287,10 @@ public interface ReactiveHyperLogLogCommands { * @param sourceKeys must not be {@literal null}. * @return */ - default Mono pfMerge(ByteBuffer destinationKey, List sourceKeys) { + default Mono pfMerge(ByteBuffer destinationKey, Collection sourceKeys) { - Assert.notNull(destinationKey, "destinationKey must not be null"); - Assert.notNull(sourceKeys, "sourceKeys must not be null"); + Assert.notNull(destinationKey, "DestinationKey must not be null!"); + Assert.notNull(sourceKeys, "SourceKeys must not be null!"); return pfMerge(Mono.just(PfMergeCommand.valuesIn(sourceKeys).into(destinationKey))).next() .map(BooleanResponse::getOutput); @@ -218,5 +303,4 @@ public interface ReactiveHyperLogLogCommands { * @return */ Flux> pfMerge(Publisher commands); - } diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveKeyCommands.java index 46bd456f2..f803a72b4 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveKeyCommands.java @@ -30,13 +30,16 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** + * Redis Key commands executed using reactive infrastructure. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface ReactiveKeyCommands { /** - * Determine if given {@code key} exists. + * Determine if given {@literal key} exists. * * @param key must not be {@literal null}. * @return @@ -49,7 +52,7 @@ public interface ReactiveKeyCommands { } /** - * Determine if given {@code key} exists. + * Determine if given {@literal key} exists. * * @param keys must not be {@literal null}. * @return @@ -57,20 +60,20 @@ public interface ReactiveKeyCommands { Flux> exists(Publisher keys); /** - * Determine the type stored at {@code key}. + * Determine the type stored at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono type(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return type(Mono.just(new KeyCommand(key))).next().map(CommandResponse::getOutput); } /** - * Determine the type stored at {@code key}. + * Determine the type stored at {@literal key}. * * @param keys must not be {@literal null}. * @return @@ -78,14 +81,14 @@ public interface ReactiveKeyCommands { Flux> type(Publisher keys); /** - * Find all keys matching the given {@code pattern}. + * Find all keys matching the given {@literal pattern}. * * @param pattern must not be {@literal null}. * @return */ default Mono> keys(ByteBuffer pattern) { - Assert.notNull(pattern, "pattern must not be null"); + Assert.notNull(pattern, "Pattern must not be null!"); return keys(Mono.just(pattern)).next().map(MultiValueResponse::getOutput); } @@ -98,7 +101,7 @@ public interface ReactiveKeyCommands { Mono randomKey(); /** - * Find all keys matching the given {@code pattern}. + * Find all keys matching the given {@literal pattern}. * * @param patterns must not be {@literal null}. * @return @@ -106,6 +109,8 @@ public interface ReactiveKeyCommands { Flux> keys(Publisher patterns); /** + * {@code RENAME} command parameters. + * * @author Christoph Strobl */ class RenameCommand extends KeyCommand { @@ -115,24 +120,46 @@ public interface ReactiveKeyCommands { private RenameCommand(ByteBuffer key, ByteBuffer newName) { super(key); + this.newName = newName; } - public static ReactiveKeyCommands.RenameCommand key(ByteBuffer key) { + /** + * Creates a new {@link RenameCommand} given a {@link ByteBuffer key}. + * + * @param key must not be {@literal null}. + * @return a new {@link RenameCommand} for {@link ByteBuffer key}. + */ + public static RenameCommand key(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new RenameCommand(key, null); } - public ReactiveKeyCommands.RenameCommand to(ByteBuffer newName) { + /** + * Applies the {@literal newName}. Constructs a new command instance with all previously configured properties. + * + * @param newName must not be {@literal null}. + * @return a new {@link RenameCommand} with {@literal newName} applied. + */ + public RenameCommand to(ByteBuffer newName) { + + Assert.notNull(newName, "New name must not be null!"); + return new RenameCommand(getKey(), newName); } + /** + * @return + */ public ByteBuffer getNewName() { return newName; } } /** - * Rename key {@code oleName} to {@code newName}. + * Rename key {@literal oleName} to {@literal newName}. * * @param key must not be {@literal null}. * @param newName must not be {@literal null}. @@ -140,15 +167,15 @@ public interface ReactiveKeyCommands { */ default Mono rename(ByteBuffer key, ByteBuffer newName) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return rename(Mono.just(RenameCommand.key(key).to(newName))).next().map(BooleanResponse::getOutput); } - Flux> rename(Publisher cmd); + Flux> rename(Publisher cmd); /** - * Rename key {@code oleName} to {@code newName} only if {@code newName} does not exist. + * Rename key {@literal oleName} to {@literal newName} only if {@literal newName} does not exist. * * @param key must not be {@literal null}. * @param newName must not be {@literal null}. @@ -156,20 +183,18 @@ public interface ReactiveKeyCommands { */ default Mono renameNX(ByteBuffer key, ByteBuffer newName) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return renameNX(Mono.just(RenameCommand.key(key).to(newName))).next().map(BooleanResponse::getOutput); } /** - * Rename key {@code oleName} to {@code newName} only if {@code newName} does not exist. + * Rename key {@literal oleName} to {@literal newName} only if {@literal newName} does not exist. * - * @param keys must not be {@literal null}. - * @param newName must not be {@literal null}. + * @param command must not be {@literal null}. * @return */ - Flux> renameNX( - Publisher command); + Flux> renameNX(Publisher command); /** * Delete {@literal key}. @@ -188,7 +213,7 @@ public interface ReactiveKeyCommands { * Delete {@literal keys} one by one. * * @param keys must not be {@literal null}. - * @return {@link Flux} of {@link DelResponse} holding the {@literal key} removed along with the deletion result. + * @return {@link Flux} of {@link NumericResponse} holding the {@literal key} removed along with the deletion result. */ Flux> del(Publisher keys); @@ -209,7 +234,7 @@ public interface ReactiveKeyCommands { * Delete multiple {@literal keys} in batches. * * @param keys must not be {@literal null}. - * @return {@link Flux} of {@link MDelResponse} holding the {@literal keys} removed along with the deletion result. + * @return {@link Flux} of {@link NumericResponse} holding the {@literal keys} removed along with the deletion result. */ Flux, Long>> mDel(Publisher> keys); } diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java index 844a40ec4..a48e5bd33 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveListCommands.java @@ -17,6 +17,7 @@ package org.springframework.data.redis.connection; import java.nio.ByteBuffer; import java.time.Duration; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -37,7 +38,10 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** + * Redis List commands executed using reactive infrastructure. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface ReactiveListCommands { @@ -50,6 +54,8 @@ public interface ReactiveListCommands { } /** + * {@code LPUSH}/{@literal RPUSH} command parameters. + * * @author Christoph Strobl */ class PushCommand extends KeyCommand { @@ -61,50 +67,102 @@ public interface ReactiveListCommands { private PushCommand(ByteBuffer key, List values, Direction direction, boolean upsert) { super(key); + this.values = values; this.upsert = upsert; this.direction = direction; } + /** + * Creates a new {@link PushCommand} for right push ({@literal RPUSH}). + * + * @return a new {@link PushCommand} for right push ({@literal RPUSH}). + */ public static PushCommand right() { return new PushCommand(null, null, Direction.RIGHT, true); } + /** + * Creates a new {@link PushCommand} for left push ({@literal LPUSH}). + * + * @return a new {@link PushCommand} for left push ({@literal LPUSH}). + */ public static PushCommand left() { return new PushCommand(null, null, Direction.LEFT, true); } + /** + * Applies the {@literal value}. Constructs a new command instance with all previously configured properties. + * + * @param value must not be {@literal null}. + * @return a new {@link PushCommand} with {@literal value} applied. + */ public PushCommand value(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new PushCommand(null, Collections.singletonList(value), direction, upsert); } + /** + * Applies a {@link List} of {@literal values}. + * + * @param values must not be {@literal null}. + * @return a new {@link PushCommand} with {@literal values} applied. + */ public PushCommand values(List values) { - return new PushCommand(null, values, direction, upsert); + + Assert.notNull(values, "Values must not be null!"); + + return new PushCommand(null, new ArrayList<>(values), direction, upsert); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link PushCommand} with {@literal key} applied. + */ public PushCommand to(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new PushCommand(key, values, direction, upsert); } + /** + * Disable upsert. Constructs a new command instance with all previously configured properties. + * + * @return a new {@link PushCommand} with upsert disabled. + */ public PushCommand ifExists() { return new PushCommand(getKey(), values, direction, false); } + /** + * @return + */ public List getValues() { return values; } + /** + * @return + */ public boolean getUpsert() { return upsert; } + /** + * @return + */ public Direction getDirection() { return direction; } } /** - * Append {@code values} to {@code key}. + * Append {@literal values} to {@literal key}. * * @param key must not be {@literal null}. * @param values must not be {@literal null}. @@ -112,29 +170,29 @@ public interface ReactiveListCommands { */ default Mono rPush(ByteBuffer key, List values) { - Assert.notNull(key, "command must not be null!"); + Assert.notNull(key, "Key must not be null!"); Assert.notNull(values, "Values must not be null!"); return push(Mono.just(PushCommand.right().values(values).to(key))).next().map(NumericResponse::getOutput); } /** - * Append {@code values} to {@code key} only if {@code key} already exists. + * Append {@literal values} to {@literal key} only if {@literal key} already exists. * * @param key must not be {@literal null}. - * @param values must not be {@literal null}. + * @param value must not be {@literal null}. * @return */ default Mono rPushX(ByteBuffer key, ByteBuffer value) { - Assert.notNull(key, "command must not be null!"); + Assert.notNull(key, "Key must not be null!"); Assert.notNull(value, "Value must not be null!"); return push(Mono.just(PushCommand.right().value(value).to(key).ifExists())).next().map(NumericResponse::getOutput); } /** - * Prepend {@code values} to {@code key}. + * Prepend {@literal values} to {@literal key}. * * @param key must not be {@literal null}. * @param values must not be {@literal null}. @@ -142,22 +200,22 @@ public interface ReactiveListCommands { */ default Mono lPush(ByteBuffer key, List values) { - Assert.notNull(key, "command must not be null!"); + Assert.notNull(key, "Key must not be null!"); Assert.notNull(values, "Values must not be null!"); return push(Mono.just(PushCommand.left().values(values).to(key))).next().map(NumericResponse::getOutput); } /** - * Prepend {@code value} to {@code key} if {@code key} already exists. + * Prepend {@literal value} to {@literal key} if {@literal key} already exists. * * @param key must not be {@literal null}. - * @param values must not be {@literal null}. + * @param value must not be {@literal null}. * @return */ default Mono lPushX(ByteBuffer key, ByteBuffer value) { - Assert.notNull(key, "command must not be null!"); + Assert.notNull(key, "Key must not be null!"); Assert.notNull(value, "Value must not be null!"); return push(Mono.just(PushCommand.left().value(value).to(key).ifExists())).next().map(NumericResponse::getOutput); @@ -172,14 +230,14 @@ public interface ReactiveListCommands { Flux> push(Publisher commands); /** - * Get the size of list stored at {@code key}. + * Get the size of list stored at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono lLen(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return lLen(Mono.just(new KeyCommand(key))).next().map(NumericResponse::getOutput); } @@ -193,7 +251,7 @@ public interface ReactiveListCommands { Flux> lLen(Publisher commands); /** - * Get elements between {@code begin} and {@code end} from list at {@code key}. + * Get elements between {@literal begin} and {@literal end} from list at {@literal key}. * * @param key must not be {@literal null}. * @param start @@ -202,7 +260,7 @@ public interface ReactiveListCommands { */ default Mono> lRange(ByteBuffer key, long start, long end) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return lRange(Mono.just(RangeCommand.key(key).fromIndex(start).toIndex(end))).next() .map(MultiValueResponse::getOutput); @@ -217,7 +275,7 @@ public interface ReactiveListCommands { Flux> lRange(Publisher commands); /** - * Trim list at {@code key} to elements between {@code begin} and {@code end}. + * Trim list at {@literal key} to elements between {@literal begin} and {@literal end}. * * @param key must not be {@literal null}. * @param start @@ -226,9 +284,11 @@ public interface ReactiveListCommands { */ default Mono lTrim(ByteBuffer key, long start, long end) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); - return lTrim(Mono.just(RangeCommand.key(key).fromIndex(start).toIndex(end))).next().map(BooleanResponse::getOutput); + return lTrim(Mono.just(RangeCommand.key(key).fromIndex(start).toIndex(end))) // + .next() // + .map(BooleanResponse::getOutput); } /** @@ -240,6 +300,8 @@ public interface ReactiveListCommands { Flux> lTrim(Publisher commands); /** + * {@code LINDEX} command parameters. + * * @author Christoph Strobl */ class LIndexCommand extends KeyCommand { @@ -252,21 +314,39 @@ public interface ReactiveListCommands { this.index = index; } - public static LIndexCommand elementAt(Long index) { + /** + * Creates a new {@link LIndexCommand} given an {@literal index}. + * + * @param index + * @return a new {@link LIndexCommand} for {@literal index}. + */ + public static LIndexCommand elementAt(long index) { return new LIndexCommand(null, index); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link LIndexCommand} with {@literal key} applied. + */ public LIndexCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new LIndexCommand(key, index); } + /** + * @return + */ public Long getIndex() { return index; } } /** - * Get element at {@code index} form list at {@code key}. + * Get element at {@literal index} form list at {@literal key}. * * @param key must not be {@literal null}. * @param index @@ -274,7 +354,7 @@ public interface ReactiveListCommands { */ default Mono lIndex(ByteBuffer key, long index) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return lIndex(Mono.just(LIndexCommand.elementAt(index).from(key))).next().map(ByteBufferResponse::getOutput); } @@ -288,6 +368,8 @@ public interface ReactiveListCommands { Flux> lIndex(Publisher commands); /** + * {@code LINSERT} command parameters. + * * @author Christoph Strobl */ class LInsertCommand extends KeyCommand { @@ -296,55 +378,104 @@ public interface ReactiveListCommands { private final ByteBuffer pivot; private final ByteBuffer value; - public LInsertCommand(ByteBuffer key, Position position, ByteBuffer pivot, ByteBuffer value) { + private LInsertCommand(ByteBuffer key, Position position, ByteBuffer pivot, ByteBuffer value) { super(key); + this.position = position; this.pivot = pivot; this.value = value; } + /** + * Creates a new {@link LInsertCommand} given a {@link ByteBuffer value}. + * + * @param value must not be {@literal null}. + * @return a new {@link LInsertCommand} for {@link ByteBuffer value}. + */ public static LInsertCommand value(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new LInsertCommand(null, null, null, value); } + /** + * Applies the before {@literal pivot}. Constructs a new command instance with all previously configured properties. + * + * @param pivot must not be {@literal null}. + * @return a new {@link LInsertCommand} with {@literal pivot} applied. + */ public LInsertCommand before(ByteBuffer pivot) { + + Assert.notNull(pivot, "Before pivot must not be null!"); + return new LInsertCommand(getKey(), Position.BEFORE, pivot, value); } + /** + * Applies the after {@literal pivot}. Constructs a new command instance with all previously configured properties. + * + * @param pivot must not be {@literal null}. + * @return a new {@link LInsertCommand} with {@literal pivot} applied. + */ public LInsertCommand after(ByteBuffer pivot) { + + Assert.notNull(pivot, "After pivot must not be null!"); + return new LInsertCommand(getKey(), Position.AFTER, pivot, value); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link LInsertCommand} with {@literal key} applied. + */ public LInsertCommand forKey(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new LInsertCommand(key, position, pivot, value); } + /** + * @return + */ public ByteBuffer getValue() { return value; } + /** + * @return + */ public Position getPosition() { return position; } + /** + * @return + */ public ByteBuffer getPivot() { return pivot; } } /** - * Insert {@code value} {@link Position#BEFORE} or {@link Position#AFTER} existing {@code pivot} for {@code key}. + * Insert {@literal value} {@link Position#BEFORE} or {@link Position#AFTER} existing {@literal pivot} for + * {@literal key}. * * @param key must not be {@literal null}. - * @param values must not be {@literal null}. + * @param position must not be {@literal null}. + * @param pivot must not be {@literal null}. + * @param value must not be {@literal null}. * @return */ default Mono lInsert(ByteBuffer key, Position position, ByteBuffer pivot, ByteBuffer value) { - Assert.notNull(key, "key must not be null!"); - Assert.notNull(position, "position must not be null!"); - Assert.notNull(pivot, "pivot must not be null!"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(position, "Position must not be null!"); + Assert.notNull(pivot, "Pivot must not be null!"); Assert.notNull(value, "Value must not be null!"); LInsertCommand command = LInsertCommand.value(value); @@ -363,6 +494,8 @@ public interface ReactiveListCommands { Flux> lInsert(Publisher commands); /** + * {@code LSET} command parameters. + * * @author Christoph Strobl */ class LSetCommand extends KeyCommand { @@ -377,29 +510,59 @@ public interface ReactiveListCommands { this.value = value; } - public static LSetCommand elementAt(Long index) { + /** + * Creates a new {@link LSetCommand} given an {@literal index}. + * + * @param index + * @return a new {@link LSetCommand} for {@literal index}. + */ + public static LSetCommand elementAt(long index) { return new LSetCommand(null, index, null); } + /** + * Applies the {@literal value}. Constructs a new command instance with all previously configured properties. + * + * @param value must not be {@literal null}. + * @return a new {@link LSetCommand} with {@literal value} applied. + */ public LSetCommand to(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new LSetCommand(getKey(), index, value); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link LSetCommand} with {@literal value} applied. + */ public LSetCommand forKey(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new LSetCommand(key, index, value); } + /** + * @return + */ public ByteBuffer getValue() { return value; } + /** + * @return + */ public Long getIndex() { return index; } } /** - * Set the {@code value} list element at {@code index}. + * Set the {@literal value} list element at {@literal index}. * * @param key must not be {@literal null}. * @param index @@ -408,8 +571,8 @@ public interface ReactiveListCommands { */ default Mono lSet(ByteBuffer key, long index, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(value, "Value must not be null!"); return lSet(Mono.just(LSetCommand.elementAt(index).to(value).forKey(key))).next().map(BooleanResponse::getOutput); } @@ -423,6 +586,8 @@ public interface ReactiveListCommands { Flux> lSet(Publisher commands); /** + * {@code LREM} command parameters. + * * @author Christoph Strobl */ class LRemCommand extends KeyCommand { @@ -431,44 +596,85 @@ public interface ReactiveListCommands { private final ByteBuffer value; private LRemCommand(ByteBuffer key, Long count, ByteBuffer value) { + super(key); + this.count = count; this.value = value; } + /** + * Creates a new {@link LRemCommand} to delete all values. + * + * @return a new {@link LRemCommand} for {@link ByteBuffer value}. + */ public static LRemCommand all() { return new LRemCommand(null, 0L, null); } - public static LRemCommand first(Long count) { + /** + * Creates a new {@link LRemCommand} to first {@literal count} values. + * + * @return a new {@link LRemCommand} to delete first {@literal count} values. + */ + public static LRemCommand first(long count) { return new LRemCommand(null, count, null); } - public static LRemCommand last(Long count) { + /** + * Creates a new {@link LRemCommand} to last {@literal count} values. + * + * @return a new {@link LRemCommand} to delete last {@literal count} values. + */ + public static LRemCommand last(long count) { Long value = count < 0L ? count : Math.negateExact(count); return new LRemCommand(null, value, null); } - public LRemCommand occurancesOf(ByteBuffer value) { + /** + * Applies the {@literal value}. Constructs a new command instance with all previously configured properties. + * + * @param value must not be {@literal null}. + * @return a new {@link LRemCommand} with {@literal value} applied. + */ + public LRemCommand occurrencesOf(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new LRemCommand(getKey(), count, value); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link LRemCommand} with {@literal key} applied. + */ public LRemCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new LRemCommand(key, count, value); } + /** + * @return + */ public Long getCount() { return count; } + /** + * @return + */ public ByteBuffer getValue() { return value; } } /** - * Removes all occurrences of {@code value} from the list stored at {@code key}. + * Removes all occurrences of {@literal value} from the list stored at {@literal key}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -476,14 +682,14 @@ public interface ReactiveListCommands { */ default Mono lRem(ByteBuffer key, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(value, "Value must not be null!"); - return lRem(Mono.just(LRemCommand.all().occurancesOf(value).from(key))).next().map(NumericResponse::getOutput); + return lRem(Mono.just(LRemCommand.all().occurrencesOf(value).from(key))).next().map(NumericResponse::getOutput); } /** - * Removes the first {@code count} occurrences of {@code value} from the list stored at {@code key}. + * Removes the first {@literal count} occurrences of {@literal value} from the list stored at {@literal key}. * * @param key must not be {@literal null}. * @param count must not be {@literal null}. @@ -492,11 +698,11 @@ public interface ReactiveListCommands { */ default Mono lRem(ByteBuffer key, Long count, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(count, "count must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(count, "Count must not be null!"); + Assert.notNull(value, "Value must not be null!"); - return lRem(Mono.just(LRemCommand.first(count).occurancesOf(value).from(key))).next() + return lRem(Mono.just(LRemCommand.first(count).occurrencesOf(value).from(key))).next() .map(NumericResponse::getOutput); } @@ -510,6 +716,8 @@ public interface ReactiveListCommands { Flux> lRem(Publisher commands); /** + * {@code LPOP}/{@literal RPOP} command parameters. + * * @author Christoph Strobl */ class PopCommand extends KeyCommand { @@ -519,49 +727,71 @@ public interface ReactiveListCommands { private PopCommand(ByteBuffer key, Direction direction) { super(key); + this.direction = direction; } + /** + * Creates a new {@link PopCommand} for right push ({@literal RPOP}). + * + * @return a new {@link PopCommand} for right push ({@literal RPOP}). + */ public static PopCommand right() { return new PopCommand(null, Direction.RIGHT); } + /** + * Creates a new {@link PopCommand} for right push ({@literal LPOP}). + * + * @return a new {@link PopCommand} for right push ({@literal LPOP}). + */ public static PopCommand left() { return new PopCommand(null, Direction.LEFT); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link LSetCommand} with {@literal value} applied. + */ public PopCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new PopCommand(key, direction); } + /** + * @return + */ public Direction getDirection() { return direction; } - } /** - * Removes and returns first element in list stored at {@code key}. + * Removes and returns first element in list stored at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono lPop(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return pop(Mono.just(PopCommand.left().from(key))).next().map(ByteBufferResponse::getOutput); } /** - * Removes and returns last element in list stored at {@code key}. + * Removes and returns last element in list stored at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono rPop(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return pop(Mono.just(PopCommand.right().from(key))).next().map(ByteBufferResponse::getOutput); } @@ -584,47 +814,89 @@ public interface ReactiveListCommands { private final Direction direction; private BPopCommand(List keys, Duration timeout, Direction direction) { + this.keys = keys; this.timeout = timeout; this.direction = direction; } + /** + * Creates a new {@link BPopCommand} for right push ({@literal BRPOP}). + * + * @return a new {@link BPopCommand} for right push ({@literal BRPOP}). + */ public static BPopCommand right() { return new BPopCommand(null, Duration.ZERO, Direction.RIGHT); } + /** + * Creates a new {@link BPopCommand} for right push ({@literal BLPOP}). + * + * @return a new {@link BPopCommand} for right push ({@literal BLPOP}). + */ public static BPopCommand left() { return new BPopCommand(null, Duration.ZERO, Direction.LEFT); } + /** + * Applies the {@literal value}. Constructs a new command instance with all previously configured properties. + * + * @param keys must not be {@literal null}. + * @return a new {@link BPopCommand} with {@literal value} applied. + */ public BPopCommand from(List keys) { - return new BPopCommand(keys, Duration.ZERO, direction); + + Assert.notNull(keys, "Keys must not be null!"); + + return new BPopCommand(new ArrayList<>(keys), Duration.ZERO, direction); } + /** + * Applies a {@link Duration timeout}. Constructs a new command instance with all previously configured properties. + * + * @param timeout must not be {@literal null}. + * @return a new {@link BPopCommand} with {@link Duration timeout} applied. + */ public BPopCommand blockingFor(Duration timeout) { + + Assert.notNull(timeout, "Timeout must not be null!"); + return new BPopCommand(keys, timeout, direction); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() + */ @Override public ByteBuffer getKey() { return null; } + /** + * @return + */ public List getKeys() { return keys; } + /** + * @return + */ public Duration getTimeout() { return timeout; } + /** + * @return + */ public Direction getDirection() { return direction; } - } /** + * Result for {@link PopCommand}/{@link BPopCommand}. + * * @author Christoph Strobl */ class PopResult { @@ -649,6 +921,8 @@ public interface ReactiveListCommands { } /** + * Result for {@link PopCommand}/{@link BPopCommand}. + * * @author Christoph Strobl */ class PopResponse extends CommandResponse { @@ -656,12 +930,11 @@ public interface ReactiveListCommands { public PopResponse(BPopCommand input, PopResult output) { super(input, output); } - } /** - * Removes and returns first element from lists stored at {@code keys}.
- * Blocks connection until element available or {@code timeout} reached. + * Removes and returns first element from lists stored at {@literal keys}.
+ * Blocks connection until element available or {@literal timeout} reached. * * @param keys must not be {@literal null}. * @param timeout must not be {@literal null}. @@ -669,15 +942,15 @@ public interface ReactiveListCommands { */ default Mono blPop(List keys, Duration timeout) { - Assert.notNull(keys, "keys must not be null."); - Assert.notNull(timeout, "timeout must not be null."); + Assert.notNull(keys, "Keys must not be null."); + Assert.notNull(timeout, "Timeout must not be null."); return bPop(Mono.just(BPopCommand.left().from(keys).blockingFor(timeout))).next().map(PopResponse::getOutput); } /** - * Removes and returns last element from lists stored at {@code keys}.
- * Blocks connection until element available or {@code timeout} reached. + * Removes and returns last element from lists stored at {@literal keys}.
+ * Blocks connection until element available or {@literal timeout} reached. * * @param keys must not be {@literal null}. * @param timeout must not be {@literal null}. @@ -685,8 +958,8 @@ public interface ReactiveListCommands { */ default Mono brPop(List keys, Duration timeout) { - Assert.notNull(keys, "keys must not be null."); - Assert.notNull(timeout, "timeout must not be null."); + Assert.notNull(keys, "Keys must not be null."); + Assert.notNull(timeout, "Timeout must not be null."); return bPop(Mono.just(BPopCommand.right().from(keys).blockingFor(timeout))).next().map(PopResponse::getOutput); } @@ -702,6 +975,8 @@ public interface ReactiveListCommands { Flux bPop(Publisher commands); /** + * {@code RPOPLPUSH} command parameters. + * * @author Christoph Strobl */ class RPopLPushCommand extends KeyCommand { @@ -714,22 +989,43 @@ public interface ReactiveListCommands { this.destination = destination; } + /** + * Creates a new {@link RPopLPushCommand} given a {@literal sourceKey}. + * + * @param sourceKey must not be {@literal null}. + * @return a new {@link RPopLPushCommand} for a {@literal sourceKey}. + */ public static RPopLPushCommand from(ByteBuffer sourceKey) { + + Assert.notNull(sourceKey, "Source key must not be null!"); + return new RPopLPushCommand(sourceKey, null); } + /** + * Applies the {@literal destinationKey}. Constructs a new command instance with all previously configured + * properties. + * + * @param destinationKey must not be {@literal null}. + * @return a new {@link BPopCommand} with {@literal value} applied. + */ public RPopLPushCommand to(ByteBuffer destinationKey) { + + Assert.notNull(destinationKey, "Destination key must not be null!"); + return new RPopLPushCommand(getKey(), destinationKey); } + /** + * @return + */ public ByteBuffer getDestination() { return destination; } - } /** - * Remove the last element from list at {@code source}, append it to {@code destination} and return its value. + * Remove the last element from list at {@literal source}, append it to {@literal destination} and return its value. * * @param source must not be {@literal null}. * @param destination must not be {@literal null}. @@ -737,10 +1033,11 @@ public interface ReactiveListCommands { */ default Mono rPopLPush(ByteBuffer source, ByteBuffer destination) { - Assert.notNull(source, "source must not be null"); - Assert.notNull(destination, "destination must not be null"); + Assert.notNull(source, "Source must not be null!"); + Assert.notNull(destination, "Destination must not be null!"); - return rPopLPush(Mono.just(RPopLPushCommand.from(source).to(destination))).next() + return rPopLPush(Mono.just(RPopLPushCommand.from(source).to(destination))) // + .next() // .map(ByteBufferResponse::getOutput); } @@ -748,13 +1045,14 @@ public interface ReactiveListCommands { * Remove the last element from list at {@link RPopLPushCommand#getKey()}, append it to * {@link RPopLPushCommand#getDestination()} and return its value. * - * @param source must not be {@literal null}. - * @param destination must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ Flux> rPopLPush(Publisher commands); /** + * {@code BRPOPLPUSH} command parameters. + * * @author Christoph Strobl */ class BRPopLPushCommand extends KeyCommand { @@ -765,34 +1063,69 @@ public interface ReactiveListCommands { private BRPopLPushCommand(ByteBuffer key, ByteBuffer destination, Duration timeout) { super(key); + this.destination = destination; this.timeout = timeout; } + /** + * Creates a new {@link BRPopLPushCommand} given a {@literal sourceKey}. + * + * @param sourceKey must not be {@literal null}. + * @return a new {@link BRPopLPushCommand} for a {@literal sourceKey}. + */ public static BRPopLPushCommand from(ByteBuffer sourceKey) { + + Assert.notNull(sourceKey, "Source key must not be null!"); + return new BRPopLPushCommand(sourceKey, null, null); } + /** + * Applies the {@literal destinationKey}. Constructs a new command instance with all previously configured + * properties. + * + * @param destinationKey must not be {@literal null}. + * @return a new {@link BRPopLPushCommand} with {@literal value} applied. + */ public BRPopLPushCommand to(ByteBuffer destinationKey) { + + Assert.notNull(destinationKey, "Destination key must not be null!"); + return new BRPopLPushCommand(getKey(), destinationKey, timeout); } + /** + * Applies a {@link Duration timeout}. Constructs a new command instance with all previously configured properties. + * + * @param timeout must not be {@literal null}. + * @return a new {@link BRPopLPushCommand} with {@link Duration timeout} applied. + */ public BRPopLPushCommand blockingFor(Duration timeout) { + + Assert.notNull(timeout, "Timeout must not be null!"); + return new BRPopLPushCommand(getKey(), destination, timeout); } + /** + * @return + */ public ByteBuffer getDestination() { return destination; } + /** + * @return + */ public Duration getTimeout() { return timeout; } } /** - * Remove the last element from list at {@code source}, append it to {@code destination} and return its value. - * Blocks connection until element available or {@code timeout} reached.
+ * Remove the last element from list at {@literal source}, append it to {@literal destination} and return its value. + * Blocks connection until element available or {@literal timeout} reached.
* * @param source must not be {@literal null}. * @param destination must not be {@literal null}. @@ -800,8 +1133,8 @@ public interface ReactiveListCommands { */ default Mono bRPopLPush(ByteBuffer source, ByteBuffer destination, Duration timeout) { - Assert.notNull(source, "source must not be null"); - Assert.notNull(destination, "destination must not be null"); + Assert.notNull(source, "Source must not be null!"); + Assert.notNull(destination, "Destination must not be null!"); return bRPopLPush(Mono.just(BRPopLPushCommand.from(source).to(destination).blockingFor(timeout))).next() .map(ByteBufferResponse::getOutput); @@ -812,8 +1145,7 @@ public interface ReactiveListCommands { * {@link BRPopLPushCommand#getDestination()} and return its value.
* Blocks connection until element available or {@link BRPopLPushCommand#getTimeout()} reached. * - * @param source must not be {@literal null}. - * @param destination must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ Flux> bRPopLPush(Publisher commands); diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveNumberCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveNumberCommands.java index 7c4957c5e..aa2252d00 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveNumberCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveNumberCommands.java @@ -26,27 +26,29 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** + * Redis numeric commands executed using reactive infrastructure. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface ReactiveNumberCommands { /** - * Increment value of {@code key} by 1. + * Increment value of {@literal key} by 1. * * @param key must not be {@literal null}. * @return */ default Mono incr(ByteBuffer key) { - - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return incr(Mono.just(new KeyCommand(key))).next().map(NumericResponse::getOutput); } /** - * Increment value of {@code key} by 1. + * Increment value of {@literal key} by 1. * * @param keys must not be {@literal null}. * @return @@ -54,6 +56,8 @@ public interface ReactiveNumberCommands { Flux> incr(Publisher keys); /** + * {@code INCRBY} command parameters. + * * @author Christoph Strobl */ class IncrByCommand extends KeyCommand { @@ -65,22 +69,43 @@ public interface ReactiveNumberCommands { this.value = value; } + /** + * Creates a new {@link IncrByCommand} given a {@link ByteBuffer key}. + * + * @param key must not be {@literal null}. + * @return a new {@link IncrByCommand} for {@link ByteBuffer key}. + */ public static IncrByCommand incr(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new IncrByCommand(key, null); } + /** + * Applies the numeric {@literal value}. Constructs a new command instance with all previously configured + * properties. + * + * @param value must not be {@literal null}. + * @return a new {@link IncrByCommand} with {@literal value} applied. + */ public IncrByCommand by(T value) { + + Assert.notNull(value, "Value must not be null!"); + return new IncrByCommand(getKey(), value); } + /** + * @return + */ public T getValue() { return value; } - } /** - * Increment value of {@code key} by {@code value}. + * Increment value of {@literal key} by {@literal value}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -88,25 +113,24 @@ public interface ReactiveNumberCommands { */ default Mono incrBy(ByteBuffer key, T value) { - - Assert.notNull(key, "key must not be null"); - Assert.notNull(value, "value must not be null"); - + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(value, "Value must not be null!"); return incrBy(Mono.just(IncrByCommand. incr(key).by(value))).next().map(NumericResponse::getOutput); } /** - * Increment value of {@code key} by {@code value}. + * Increment value of {@literal key} by {@literal value}. * - * @param keys must not be {@literal null}. - * @param value must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ Flux, T>> incrBy( Publisher> commands); /** + * {@code DECRBY} command parameters. + * * @author Christoph Strobl */ class DecrByCommand extends KeyCommand { @@ -118,37 +142,56 @@ public interface ReactiveNumberCommands { this.value = value; } - public static ReactiveNumberCommands.DecrByCommand decr(ByteBuffer key) { + /** + * Creates a new {@link DecrByCommand} given a {@link ByteBuffer key}. + * + * @param key must not be {@literal null}. + * @return a new {@link DecrByCommand} for {@link ByteBuffer key}. + */ + public static DecrByCommand decr(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new DecrByCommand(key, null); } - public ReactiveNumberCommands.DecrByCommand by(T value) { + /** + * Applies the numeric {@literal value}. Constructs a new command instance with all previously configured + * properties. + * + * @param value must not be {@literal null}. + * @return a new {@link DecrByCommand} with {@literal value} applied. + */ + public DecrByCommand by(T value) { + + Assert.notNull(value, "Value must not be null!"); + return new DecrByCommand(getKey(), value); } + /** + * @return + */ public T getValue() { return value; } - } /** - * Decrement value of {@code key} by 1. + * Decrement value of {@literal key} by 1. * * @param key must not be {@literal null}. * @return */ default Mono decr(ByteBuffer key) { - - Assert.notNull(key, "key must not be null"); - + Assert.notNull(key, "Key must not be null!"); return decr(Mono.just(new KeyCommand(key))).next().map(NumericResponse::getOutput); } /** - * Decrement value of {@code key} by 1. + * Decrement value of {@literal key} by 1. * * @param keys must not be {@literal null}. * @return @@ -156,7 +199,7 @@ public interface ReactiveNumberCommands { Flux> decr(Publisher keys); /** - * Decrement value of {@code key} by {@code value}. + * Decrement value of {@literal key} by {@literal value}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -164,25 +207,23 @@ public interface ReactiveNumberCommands { */ default Mono decrBy(ByteBuffer key, T value) { - - Assert.notNull(key, "key must not be null"); - Assert.notNull(value, "value must not be null"); - + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(value, "Value must not be null!"); return decrBy(Mono.just(DecrByCommand. decr(key).by(value))).next().map(NumericResponse::getOutput); } /** - * Decrement value of {@code key} by {@code value}. + * Decrement value of {@literal key} by {@literal value}. * - * @param keys must not be {@literal null}. - * @param value must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ - Flux, T>> decrBy( - Publisher> commands); + Flux, T>> decrBy(Publisher> commands); /** + * {@code HINCRBY} command parameters. + * * @author Christoph Strobl */ class HIncrByCommand extends KeyCommand { @@ -193,33 +234,68 @@ public interface ReactiveNumberCommands { private HIncrByCommand(ByteBuffer key, ByteBuffer field, T value) { super(key); + this.field = field; this.value = value; } + /** + * Creates a new {@link HIncrByCommand} given a {@link ByteBuffer key}. + * + * @param field must not be {@literal null}. + * @return a new {@link HIncrByCommand} for {@link ByteBuffer key}. + */ public static HIncrByCommand incr(ByteBuffer field) { + + Assert.notNull(field, "Field must not be null!"); + return new HIncrByCommand(null, field, null); } + /** + * Applies the numeric {@literal value}. Constructs a new command instance with all previously configured + * properties. + * + * @param value must not be {@literal null}. + * @return a new {@link HIncrByCommand} with {@literal value} applied. + */ public HIncrByCommand by(T value) { + + Assert.notNull(value, "Value must not be null!"); + return new HIncrByCommand(getKey(), field, value); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link HIncrByCommand} with {@literal key} applied. + */ public HIncrByCommand forKey(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new HIncrByCommand(key, field, value); } + /** + * @return + */ public T getValue() { return value; } + /** + * @return + */ public ByteBuffer getField() { return field; } } /** - * Increment {@code value} of a hash {@code field} by the given {@code value}. + * Increment {@literal value} of a hash {@literal field} by the given {@literal value}. * * @param key must not be {@literal null}. * @param field must not be {@literal null}. @@ -228,18 +304,16 @@ public interface ReactiveNumberCommands { */ default Mono hIncrBy(ByteBuffer key, ByteBuffer field, T value) { - - Assert.notNull(key, "key must not be null"); - Assert.notNull(field, "field must not be null"); - Assert.notNull(value, "value must not be null"); - + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(field, "Field must not be null!"); + Assert.notNull(value, "Value must not be null!"); return hIncrBy(Mono.just(HIncrByCommand. incr(field).by(value).forKey(key))).next() .map(NumericResponse::getOutput); } /** - * Increment {@code value} of a hash {@code field} by the given {@code value}. + * Increment {@literal value} of a hash {@literal field} by the given {@literal value}. * * @return */ diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/ReactiveRedisConnection.java index d380341c8..620209353 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveRedisConnection.java @@ -17,21 +17,33 @@ package org.springframework.data.redis.connection; import java.io.Closeable; import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; -import java.util.function.Supplier; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.DirectFieldAccessor; import org.springframework.data.domain.Range; +import org.springframework.util.Assert; import lombok.Data; /** + * Redis connection using reactive infrastructure declaring entry points for reactive command execution. + *

+ * {@link ReactiveRedisConnection} is typically implemented by a stateful object that requires to be {@link #close() + * closed} once it is no longer required. + *

+ * Commands can be either executed by passing plain arguments like {@code key}, {@code value} or wrapped inside a + * command stream. Streaming command execution accepts {@link org.reactivestreams.Publisher} of a particular + * {@link Command}. Commands are executed at the time their emission. + *

+ * Arguments are binary-safe by using {@link ByteBuffer} arguments. Expect {@link ByteBuffer} to be consumed by + * {@link ReactiveRedisConnection} invocation or during execution. Any {@link ByteBuffer} used as method parameter + * should not be altered after invocation. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 + * @see Command + * @see CommandResponse + * @see KeyCommand */ public interface ReactiveRedisConnection extends Closeable { @@ -85,7 +97,7 @@ public interface ReactiveRedisConnection extends Closeable { ReactiveHashCommands hashCommands(); /** - * Get {@link ReacktiveGeoCommands} + * Get {@link ReactiveGeoCommands} * * @return never {@literal null}. */ @@ -98,86 +110,48 @@ public interface ReactiveRedisConnection extends Closeable { */ ReactiveHyperLogLogCommands hyperLogLogCommands(); + /** + * Base interface for Redis commands executed with a reactive infrastructure. + * + * @author Christoph Strobl + * @author Mark Paluch + */ interface Command { + /** + * @return the key related to this command. + */ ByteBuffer getKey(); + /** + * @return command name as {@link String}. + */ default String getName() { return getClass().getSimpleName().replace("Command", "").toUpperCase(); } - - static Builder create(Class type) { - return new CommandBuilder(type); - } - - interface Builder extends Consumer { - - default Builder forKey(String key) { - return forKey(key.getBytes(Charset.forName("UTF-8"))); - } - - default Builder forKey(byte[] key) { - return forKey(ByteBuffer.wrap(key)); - } - - default Builder forKey(ByteBuffer key) { - return forKey(() -> key); - } - - Builder forKey(Supplier keySupplier); - - T build(); - } - - class CommandBuilder implements Builder { - - List argumentList = new ArrayList<>(); - - Class type; - Supplier key; - - public CommandBuilder(Class type) { - this.type = type; - } - - public Builder forKey(Supplier key) { - this.key = key; - return this; - } - - @Override - public void accept(Object t) { - argumentList.add(t); - } - - @Override - public T build() { - - try { - T x = BeanUtils.instantiateClass(type); - - DirectFieldAccessor dfa = new DirectFieldAccessor(x); - dfa.setPropertyValue("key", key); - return x; - - } catch (IllegalArgumentException | SecurityException e) { - throw new IllegalArgumentException(" ¯\\_(ツ)_/¯", e); - } - } - } } /** + * {@link Command} for key-bound operations. + * * @author Christoph Strobl */ class KeyCommand implements Command { private ByteBuffer key; + /** + * Creates a new {@link KeyCommand} given a {@code key}. + * + * @param key must not be {@literal null}. + */ public KeyCommand(ByteBuffer key) { this.key = key; } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() + */ @Override public ByteBuffer getKey() { return key; @@ -191,33 +165,77 @@ public interface ReactiveRedisConnection extends Closeable { Range range; - public RangeCommand(ByteBuffer key, Range range) { + /** + * Creates a new {@link RangeCommand} given a {@code key} and {@link Range}. + * + * @param key must not be {@literal null}. + * @param range may be {@literal null} if unbounded. + */ + private RangeCommand(ByteBuffer key, Range range) { super(key); this.range = range != null ? range : new Range<>(0L, Long.MAX_VALUE); } + /** + * Creates a new {@link RangeCommand} given a {@code key}. + * + * @param key must not be {@literal null}. + * @return a new {@link RangeCommand} for {@code key}. + */ public static RangeCommand key(ByteBuffer key) { return new RangeCommand(key, null); } + /** + * Applies a {@link Range}. Constructs a new command instance with all previously configured properties. + * + * @param range must not be {@literal null}. + * @return a new {@link RangeCommand} with {@link Range} applied. + */ public RangeCommand within(Range range) { + + Assert.notNull(range, "Range must not be null!"); + return new RangeCommand(getKey(), range); } - public RangeCommand fromIndex(Long start) { + /** + * Applies a lower bound to the {@link Range}. Constructs a new command instance with all previously configured + * properties. + * + * @param start + * @return a new {@link RangeCommand} with the lower bound applied. + */ + public RangeCommand fromIndex(long start) { return new RangeCommand(getKey(), new Range<>(start, range.getUpperBound())); } - public RangeCommand toIndex(Long end) { + /** + * Applies an upper bound to the {@link Range}. Constructs a new command instance with all previously configured + * properties. + * + * @param end + * @return a new {@link RangeCommand} with the upper bound applied. + */ + public RangeCommand toIndex(long end) { return new RangeCommand(getKey(), new Range<>(range.getLowerBound(), end)); } + /** + * @return the {@link Range}. + */ public Range getRange() { return range; } } + /** + * Base class for command responses. + * + * @param command input type. + * @param command output type. + */ @Data class CommandResponse { @@ -225,6 +243,9 @@ public interface ReactiveRedisConnection extends Closeable { private final O output; } + /** + * {@link CommandResponse} implementation for {@link Boolean} responses. + */ class BooleanResponse extends CommandResponse { public BooleanResponse(I input, Boolean output) { @@ -232,6 +253,9 @@ public interface ReactiveRedisConnection extends Closeable { } } + /** + * {@link CommandResponse} implementation for {@link ByteBuffer} responses. + */ class ByteBufferResponse extends CommandResponse { public ByteBufferResponse(I input, ByteBuffer output) { @@ -239,6 +263,9 @@ public interface ReactiveRedisConnection extends Closeable { } } + /** + * {@link CommandResponse} implementation for {@link List} responses. + */ class MultiValueResponse extends CommandResponse> { public MultiValueResponse(I input, List output) { @@ -246,11 +273,13 @@ public interface ReactiveRedisConnection extends Closeable { } } + /** + * {@link CommandResponse} implementation for {@link Number numeric} responses. + */ class NumericResponse extends CommandResponse { public NumericResponse(I input, O output) { super(input, output); } } - } diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveSetCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveSetCommands.java index 4801874e4..89d262bcf 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveSetCommands.java @@ -16,6 +16,8 @@ package org.springframework.data.redis.connection; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -33,12 +35,17 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** + * Redis Set commands executed using reactive infrastructure. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface ReactiveSetCommands { /** + * {@code SADD} command parameters. + * * @author Christoph Strobl */ class SAddCommand extends KeyCommand { @@ -48,28 +55,59 @@ public interface ReactiveSetCommands { private SAddCommand(ByteBuffer key, List values) { super(key); + this.values = values; } - public static SAddCommand value(ByteBuffer values) { - return values(Collections.singletonList(values)); + /** + * Creates a new {@link SAddCommand} given a {@literal value}. + * + * @param value must not be {@literal null}. + * @return a new {@link SAddCommand} for a {@literal value}. + */ + public static SAddCommand value(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + + return values(Collections.singletonList(value)); } - public static SAddCommand values(List values) { - return new SAddCommand(null, values); + /** + * Creates a new {@link SAddCommand} given a {@link Collection} of values. + * + * @param values must not be {@literal null}. + * @return a new {@link SAddCommand} for a {@link Collection} of values. + */ + public static SAddCommand values(Collection values) { + + Assert.notNull(values, "Values must not be null!"); + + return new SAddCommand(null, new ArrayList<>(values)); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link SAddCommand} with {@literal key} applied. + */ public SAddCommand to(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new SAddCommand(key, values); } + /** + * @return + */ public List getValues() { return values; } } /** - * Add given {@code value} to set at {@code key}. + * Add given {@literal value} to set at {@literal key}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -77,22 +115,22 @@ public interface ReactiveSetCommands { */ default Mono sAdd(ByteBuffer key, ByteBuffer value) { - Assert.notNull(value, "value must not be null"); + Assert.notNull(value, "Value must not be null!"); return sAdd(key, Collections.singletonList(value)); } /** - * Add given {@code values} to set at {@code key}. + * Add given {@literal values} to set at {@literal key}. * * @param key must not be {@literal null}. * @param values must not be {@literal null}. * @return */ - default Mono sAdd(ByteBuffer key, List values) { + default Mono sAdd(ByteBuffer key, Collection values) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(values, "values must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(values, "Values must not be null!"); return sAdd(Mono.just(SAddCommand.values(values).to(key))).next().map(NumericResponse::getOutput); } @@ -106,37 +144,70 @@ public interface ReactiveSetCommands { Flux> sAdd(Publisher commands); /** + * {@code SREM} command parameters. + * * @author Christoph Strobl */ class SRemCommand extends KeyCommand { private final List values; - public SRemCommand(ByteBuffer key, List values) { + private SRemCommand(ByteBuffer key, List values) { super(key); + this.values = values; } - public static SRemCommand value(ByteBuffer values) { - return values(Collections.singletonList(values)); + /** + * Creates a new {@link SRemCommand} given a {@literal value}. + * + * @param value must not be {@literal null}. + * @return a new {@link SRemCommand} for a {@literal value}. + */ + public static SRemCommand value(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + + return values(Collections.singletonList(value)); } - public static SRemCommand values(List values) { - return new SRemCommand(null, values); + /** + * Creates a new {@link SRemCommand} given a {@link Collection} of values. + * + * @param values must not be {@literal null}. + * @return a new {@link SRemCommand} for a {@link Collection} of values. + */ + public static SRemCommand values(Collection values) { + + Assert.notNull(values, "Values must not be null!"); + + return new SRemCommand(null, new ArrayList<>(values)); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link SRemCommand} with {@literal key} applied. + */ public SRemCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new SRemCommand(key, values); } + /** + * @return + */ public List getValues() { return values; } } /** - * Remove given {@code value} from set at {@code key} and return the number of removed elements. + * Remove given {@literal value} from set at {@literal key} and return the number of removed elements. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -144,22 +215,22 @@ public interface ReactiveSetCommands { */ default Mono sRem(ByteBuffer key, ByteBuffer value) { - Assert.notNull(value, "value must not be null"); + Assert.notNull(value, "Value must not be null!"); return sRem(key, Collections.singletonList(value)); } /** - * Remove given {@code values} from set at {@code key} and return the number of removed elements. + * Remove given {@literal values} from set at {@literal key} and return the number of removed elements. * * @param key must not be {@literal null}. * @param values must not be {@literal null}. * @return */ - default Mono sRem(ByteBuffer key, List values) { + default Mono sRem(ByteBuffer key, Collection values) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(values, "values must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(values, "Values must not be null!"); return sRem(Mono.just(SRemCommand.values(values).from(key))).next().map(NumericResponse::getOutput); } @@ -173,14 +244,14 @@ public interface ReactiveSetCommands { Flux> sRem(Publisher commands); /** - * Remove and return a random member from set at {@code key}. + * Remove and return a random member from set at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono sPop(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return sPop(Mono.just(new KeyCommand(key))).next().map(ByteBufferResponse::getOutput); } @@ -194,6 +265,8 @@ public interface ReactiveSetCommands { Flux> sPop(Publisher commands); /** + * {@code SMOVE} command parameters. + * * @author Christoph Strobl */ class SMoveCommand extends KeyCommand { @@ -208,29 +281,63 @@ public interface ReactiveSetCommands { this.value = value; } + /** + * Creates a new {@link SMoveCommand} given a {@literal value}. + * + * @param value must not be {@literal null}. + * @return a new {@link SMoveCommand} for a {@literal value}. + */ public static SMoveCommand value(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new SMoveCommand(null, null, value); } + /** + * Applies the {@literal source} key. Constructs a new command instance with all previously configured properties. + * + * @param source must not be {@literal null}. + * @return a new {@link SMoveCommand} with {@literal source} applied. + */ public SMoveCommand from(ByteBuffer source) { + + Assert.notNull(source, "Source key must not be null!"); + return new SMoveCommand(source, destination, value); } + /** + * Applies the {@literal destination} key. Constructs a new command instance with all previously configured + * properties. + * + * @param destination must not be {@literal null}. + * @return a new {@link SMoveCommand} with {@literal destination} applied. + */ public SMoveCommand to(ByteBuffer destination) { + + Assert.notNull(destination, "Destination key must not be null!"); + return new SMoveCommand(getKey(), destination, value); } + /** + * @return + */ public ByteBuffer getDestination() { return destination; } + /** + * @return + */ public ByteBuffer getValue() { return value; } } /** - * Move {@code value} from {@code sourceKey} to {@code destinationKey} + * Move {@literal value} from {@literal sourceKey} to {@literal destinationKey} * * @param sourceKey must not be {@literal null}. * @param destinationKey must not be {@literal null}. @@ -239,9 +346,9 @@ public interface ReactiveSetCommands { */ default Mono sMove(ByteBuffer sourceKey, ByteBuffer destinationKey, ByteBuffer value) { - Assert.notNull(sourceKey, "sourceKey must not be null"); - Assert.notNull(destinationKey, "destinationKey must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(sourceKey, "SourceKey must not be null!"); + Assert.notNull(destinationKey, "DestinationKey must not be null!"); + Assert.notNull(value, "Value must not be null!"); return sMove(Mono.just(SMoveCommand.value(value).from(sourceKey).to(destinationKey))).next() .map(BooleanResponse::getOutput); @@ -256,14 +363,14 @@ public interface ReactiveSetCommands { Flux> sMove(Publisher commands); /** - * Get size of set at {@code key}. + * Get size of set at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono sCard(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return sCard(Mono.just(new KeyCommand(key))).next().map(NumericResponse::getOutput); } @@ -277,6 +384,8 @@ public interface ReactiveSetCommands { Flux> sCard(Publisher commands); /** + * {@code SISMEMBER} command parameters. + * * @author Christoph Strobl */ class SIsMemberCommand extends KeyCommand { @@ -286,24 +395,46 @@ public interface ReactiveSetCommands { private SIsMemberCommand(ByteBuffer key, ByteBuffer value) { super(key); + this.value = value; } + /** + * Creates a new {@link SIsMemberCommand} given a {@literal value}. + * + * @param value must not be {@literal null}. + * @return a new {@link SIsMemberCommand} for a {@literal value}. + */ public static SIsMemberCommand value(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new SIsMemberCommand(null, value); } + /** + * Applies the {@literal set} key. Constructs a new command instance with all previously configured properties. + * + * @param set must not be {@literal null}. + * @return a new {@link SIsMemberCommand} with {@literal set} applied. + */ public SIsMemberCommand of(ByteBuffer set) { + + Assert.notNull(set, "Set key must not be null!"); + return new SIsMemberCommand(set, value); } + /** + * @return + */ public ByteBuffer getValue() { return value; } } /** - * Check if set at {@code key} contains {@code value}. + * Check if set at {@literal key} contains {@literal value}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -311,8 +442,8 @@ public interface ReactiveSetCommands { */ default Mono sIsMember(ByteBuffer key, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(value, "Value must not be null!"); return sIsMember(Mono.just(SIsMemberCommand.value(value).of(key))).next().map(BooleanResponse::getOutput); } @@ -326,6 +457,8 @@ public interface ReactiveSetCommands { Flux> sIsMember(Publisher commands); /** + * {@code SINTER} command parameters. + * * @author Christoph Strobl */ class SInterCommand implements Command { @@ -336,29 +469,44 @@ public interface ReactiveSetCommands { this.keys = keys; } - public static SInterCommand keys(List keys) { - return new SInterCommand(keys); + /** + * Creates a new {@link SInterCommand} given a {@link Collection} of keys. + * + * @param keys must not be {@literal null}. + * @return a new {@link SInterCommand} for a {@link Collection} of values. + */ + public static SInterCommand keys(Collection keys) { + + Assert.notNull(keys, "Keys must not be null!"); + + return new SInterCommand(new ArrayList<>(keys)); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() + */ @Override public ByteBuffer getKey() { return null; } + /** + * @return + */ public List getKeys() { return keys; } } /** - * Returns the members intersecting all given sets at {@code keys}. + * Returns the members intersecting all given sets at {@literal keys}. * * @param keys must not be {@literal null}. * @return */ - default Mono> sInter(List keys) { + default Mono> sInter(Collection keys) { - Assert.notNull(keys, "keys must not be null"); + Assert.notNull(keys, "Keys must not be null!"); return sInter(Mono.just(SInterCommand.keys(keys))).next().map(MultiValueResponse::getOutput); } @@ -372,6 +520,8 @@ public interface ReactiveSetCommands { Flux> sInter(Publisher commands); /** + * {@code SINTERSTORE} command parameters. + * * @author Christoph Strobl */ class SInterStoreCommand extends KeyCommand { @@ -381,40 +531,63 @@ public interface ReactiveSetCommands { private SInterStoreCommand(ByteBuffer key, List keys) { super(key); + this.keys = keys; } - public static SInterStoreCommand keys(List keys) { - return new SInterStoreCommand(null, keys); + /** + * Creates a new {@link SInterStoreCommand} given a {@link Collection} of keys. + * + * @param keys must not be {@literal null}. + * @return a new {@link SInterStoreCommand} for a {@link Collection} of values. + */ + public static SInterStoreCommand keys(Collection keys) { + + Assert.notNull(keys, "Keys must not be null!"); + + return new SInterStoreCommand(null, new ArrayList<>(keys)); } + /** + * Applies the {@literal key} at which the result is stored. Constructs a new command instance with all previously + * configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link SInterStoreCommand} with {@literal key} applied. + */ public SInterStoreCommand storeAt(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new SInterStoreCommand(key, keys); } + /** + * @return + */ public List getKeys() { return keys; } } /** - * Intersect all given sets at {@code keys} and store result in {@code destinationKey}. + * Intersect all given sets at {@literal keys} and store result in {@literal destinationKey}. * * @param destinationKey must not be {@literal null}. * @param keys must not be {@literal null}. - * @return size of set stored a {@code destinationKey}. + * @return size of set stored a {@literal destinationKey}. */ - default Mono sInterStore(ByteBuffer destinationKey, List keys) { + default Mono sInterStore(ByteBuffer destinationKey, Collection keys) { - Assert.notNull(destinationKey, "destinationKey must not be null"); - Assert.notNull(keys, "keys must not be null"); + Assert.notNull(destinationKey, "DestinationKey must not be null!"); + Assert.notNull(keys, "Keys must not be null!"); return sInterStore(Mono.just(SInterStoreCommand.keys(keys).storeAt(destinationKey))).next() .map(NumericResponse::getOutput); } /** - * Intersect all given sets at {@code keys} and store result in {@code destinationKey}. + * Intersect all given sets at {@literal keys} and store result in {@literal destinationKey}. * * @param commands must not be {@literal null}. * @return @@ -422,6 +595,8 @@ public interface ReactiveSetCommands { Flux> sInterStore(Publisher commands); /** + * {@code SUNION} command parameters. + * * @author Christoph Strobl */ class SUnionCommand implements Command { @@ -432,29 +607,44 @@ public interface ReactiveSetCommands { this.keys = keys; } - public static SUnionCommand keys(List keys) { - return new SUnionCommand(keys); + /** + * Creates a new {@link SUnionCommand} given a {@link Collection} of keys. + * + * @param keys must not be {@literal null}. + * @return a new {@link SUnionCommand} for a {@link Collection} of values. + */ + public static SUnionCommand keys(Collection keys) { + + Assert.notNull(keys, "Keys must not be null!"); + + return new SUnionCommand(new ArrayList<>(keys)); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() + */ @Override public ByteBuffer getKey() { return null; } + /** + * @return + */ public List getKeys() { return keys; } } /** - * Returns the members intersecting all given sets at {@code keys}. + * Returns the members intersecting all given sets at {@literal keys}. * * @param keys must not be {@literal null}. * @return */ - default Mono> sUnion(List keys) { + default Mono> sUnion(Collection keys) { - Assert.notNull(keys, "keys must not be null"); + Assert.notNull(keys, "Keys must not be null!"); return sUnion(Mono.just(SUnionCommand.keys(keys))).next().map(MultiValueResponse::getOutput); } @@ -477,40 +667,63 @@ public interface ReactiveSetCommands { private SUnionStoreCommand(ByteBuffer key, List keys) { super(key); + this.keys = keys; } - public static SUnionStoreCommand keys(List keys) { - return new SUnionStoreCommand(null, keys); + /** + * Creates a new {@link SUnionStoreCommand} given a {@link Collection} of keys. + * + * @param keys must not be {@literal null}. + * @return a new {@link SUnionStoreCommand} for a {@link Collection} of values. + */ + public static SUnionStoreCommand keys(Collection keys) { + + Assert.notNull(keys, "Keys must not be null!"); + + return new SUnionStoreCommand(null, new ArrayList<>(keys)); } + /** + * Applies the {@literal key} at which the result is stored. Constructs a new command instance with all previously + * configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link SUnionStoreCommand} with {@literal key} applied. + */ public SUnionStoreCommand storeAt(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new SUnionStoreCommand(key, keys); } + /** + * @return + */ public List getKeys() { return keys; } } /** - * Union all given sets at {@code keys} and store result in {@code destinationKey}. + * Union all given sets at {@literal keys} and store result in {@literal destinationKey}. * * @param destinationKey must not be {@literal null}. * @param keys must not be {@literal null}. - * @return size of set stored a {@code destinationKey}. + * @return size of set stored a {@literal destinationKey}. */ - default Mono sUnionStore(ByteBuffer destinationKey, List keys) { + default Mono sUnionStore(ByteBuffer destinationKey, Collection keys) { - Assert.notNull(destinationKey, "destinationKey must not be null"); - Assert.notNull(keys, "keys must not be null"); + Assert.notNull(destinationKey, "DestinationKey must not be null!"); + Assert.notNull(keys, "Keys must not be null!"); return sUnionStore(Mono.just(SUnionStoreCommand.keys(keys).storeAt(destinationKey))).next() .map(NumericResponse::getOutput); } /** - * Union all given sets at {@code keys} and store result in {@code destinationKey}. + * Union all given sets at {@literal keys} and store result in {@literal destinationKey}. * * @param commands must not be {@literal null}. * @return @@ -518,6 +731,8 @@ public interface ReactiveSetCommands { Flux> sUnionStore(Publisher commands); /** + * {@code SDIFF} command parameters. + * * @author Christoph Strobl */ class SDiffCommand implements Command { @@ -528,29 +743,44 @@ public interface ReactiveSetCommands { this.keys = keys; } - public static SDiffCommand keys(List keys) { - return new SDiffCommand(keys); + /** + * Creates a new {@link SDiffCommand} given a {@link Collection} of keys. + * + * @param keys must not be {@literal null}. + * @return a new {@link SDiffCommand} for a {@link Collection} of values. + */ + public static SDiffCommand keys(Collection keys) { + + Assert.notNull(keys, "Keys must not be null!"); + + return new SDiffCommand(new ArrayList<>(keys)); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() + */ @Override public ByteBuffer getKey() { return null; } + /** + * @return + */ public List getKeys() { return keys; } } /** - * Returns the diff of the members of all given sets at {@code keys}. + * Returns the diff of the members of all given sets at {@literal keys}. * * @param keys must not be {@literal null}. * @return */ - default Mono> sDiff(List keys) { + default Mono> sDiff(Collection keys) { - Assert.notNull(keys, "keys must not be null"); + Assert.notNull(keys, "Keys must not be null!"); return sDiff(Mono.just(SDiffCommand.keys(keys))).next().map(MultiValueResponse::getOutput); } @@ -564,6 +794,8 @@ public interface ReactiveSetCommands { Flux> sDiff(Publisher commands); /** + * {@code SDIFFSTORE} command parameters. + * * @author Christoph Strobl */ class SDiffStoreCommand extends KeyCommand { @@ -573,40 +805,63 @@ public interface ReactiveSetCommands { private SDiffStoreCommand(ByteBuffer key, List keys) { super(key); + this.keys = keys; } - public static SDiffStoreCommand keys(List keys) { - return new SDiffStoreCommand(null, keys); + /** + * Creates a new {@link SDiffStoreCommand} given a {@link Collection} of keys. + * + * @param keys must not be {@literal null}. + * @return a new {@link SDiffStoreCommand} for a {@link Collection} of values. + */ + public static SDiffStoreCommand keys(Collection keys) { + + Assert.notNull(keys, "Keys must not be null!"); + + return new SDiffStoreCommand(null, new ArrayList<>(keys)); } + /** + * Applies the {@literal key} at which the result is stored. Constructs a new command instance with all previously + * configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link SDiffStoreCommand} with {@literal key} applied. + */ public SDiffStoreCommand storeAt(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new SDiffStoreCommand(key, keys); } + /** + * @return + */ public List getKeys() { return keys; } } /** - * Diff all given sets at {@code keys} and store result in {@code destinationKey}. + * Diff all given sets at {@literal keys} and store result in {@literal destinationKey}. * * @param destinationKey must not be {@literal null}. * @param keys must not be {@literal null}. - * @return size of set stored a {@code destinationKey}. + * @return size of set stored a {@literal destinationKey}. */ - default Mono sDiffStore(ByteBuffer destinationKey, List keys) { + default Mono sDiffStore(ByteBuffer destinationKey, Collection keys) { - Assert.notNull(destinationKey, "destinationKey must not be null"); - Assert.notNull(keys, "keys must not be null"); + Assert.notNull(destinationKey, "DestinationKey must not be null!"); + Assert.notNull(keys, "Keys must not be null!"); return sDiffStore(Mono.just(SDiffStoreCommand.keys(keys).storeAt(destinationKey))).next() .map(NumericResponse::getOutput); } /** - * Diff all given sets at {@code keys} and store result in {@code destinationKey}. + * Diff all given sets at {@literal keys} and store result in {@literal destinationKey}. * * @param commands must not be {@literal null}. * @return @@ -614,14 +869,14 @@ public interface ReactiveSetCommands { Flux> sDiffStore(Publisher commands); /** - * Get all elements of set at {@code key}. + * Get all elements of set at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono> sMembers(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return sMembers(Mono.just(new KeyCommand(key))).next().map(MultiValueResponse::getOutput); } @@ -635,6 +890,8 @@ public interface ReactiveSetCommands { Flux> sMembers(Publisher commands); /** + * {@code SRANDMEMBER} command parameters. + * * @author Christoph Strobl */ class SRandMembersCommand extends KeyCommand { @@ -647,25 +904,48 @@ public interface ReactiveSetCommands { this.count = count; } - public static SRandMembersCommand valueCount(Long nrValuesToRetrieve) { + /** + * Creates a new {@link SRandMembersCommand} given the number of values to retrieve. + * + * @param nrValuesToRetrieve + * @return a new {@link SRandMembersCommand} for a number of values to retrieve. + */ + public static SRandMembersCommand valueCount(long nrValuesToRetrieve) { return new SRandMembersCommand(null, nrValuesToRetrieve); } + /** + * Creates a new {@link SRandMembersCommand} to retrieve one random member. + * + * @return a new {@link SRandMembersCommand} to retrieve one random member. + */ public static SRandMembersCommand singleValue() { return new SRandMembersCommand(null, null); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link SRandMembersCommand} with {@literal key} applied. + */ public SRandMembersCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new SRandMembersCommand(key, count); } + /** + * @return + */ public Optional getCount() { return Optional.ofNullable(count); } } /** - * Get random element from set at {@code key}. + * Get random element from set at {@literal key}. * * @param key must not be {@literal null}. * @return @@ -675,7 +955,7 @@ public interface ReactiveSetCommands { } /** - * Get {@code count} random elements from set at {@code key}. + * Get {@literal count} random elements from set at {@literal key}. * * @param key must not be {@literal null}. * @param count must not be {@literal null}. @@ -683,8 +963,8 @@ public interface ReactiveSetCommands { */ default Mono> sRandMember(ByteBuffer key, Long count) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(count, "count must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(count, "Count must not be null!"); return sRandMember(Mono.just(SRandMembersCommand.valueCount(count).from(key))).next() .map(MultiValueResponse::getOutput); diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java index d2726555c..5d92b9122 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveStringCommands.java @@ -16,6 +16,8 @@ package org.springframework.data.redis.connection; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; @@ -25,6 +27,7 @@ import org.springframework.data.domain.Range; import org.springframework.data.redis.connection.ReactiveRedisConnection.BooleanResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.ByteBufferResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.Command; +import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand; import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiValueResponse; import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; @@ -38,12 +41,17 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** + * Redis String commands executed using reactive infrastructure. + * * @author Christoph Strobl + * @author Mark Paluch * @since 2.0 */ public interface ReactiveStringCommands { /** + * {@code SET} command parameters. + * * @author Christoph Strobl */ class SetCommand extends KeyCommand { @@ -55,35 +63,81 @@ public interface ReactiveStringCommands { private SetCommand(ByteBuffer key, ByteBuffer value, Expiration expiration, SetOption option) { super(key); + this.value = value; this.expiration = expiration; this.option = option; } - public static ReactiveStringCommands.SetCommand set(ByteBuffer key) { + /** + * Creates a new {@link SetCommand} given a {@literal key}. + * + * @param key must not be {@literal null}. + * @return a new {@link SetCommand} for a {@literal key}. + */ + public static SetCommand set(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new SetCommand(key, null, null, null); } - public ReactiveStringCommands.SetCommand value(ByteBuffer value) { + /** + * Applies the {@literal value}. Constructs a new command instance with all previously configured properties. + * + * @param value must not be {@literal null}. + * @return a new {@link SetCommand} with {@literal value} applied. + */ + public SetCommand value(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new SetCommand(getKey(), value, expiration, option); } - public ReactiveStringCommands.SetCommand expiring(Expiration expiration) { + /** + * Applies {@link Expiration}. Constructs a new command instance with all previously configured properties. + * + * @param expiration must not be {@literal null}. + * @return a new {@link SetCommand} with {@link Expiration} applied. + */ + public SetCommand expiring(Expiration expiration) { + + Assert.notNull(expiration, "Expiration must not be null!"); + return new SetCommand(getKey(), value, expiration, option); } - public ReactiveStringCommands.SetCommand withSetOption(SetOption option) { + /** + * Applies {@link SetOption}. Constructs a new command instance with all previously configured properties. + * + * @param option must not be {@literal null}. + * @return a new {@link SetCommand} with {@link SetOption} applied. + */ + public SetCommand withSetOption(SetOption option) { + + Assert.notNull(option, "SetOption must not be null!"); + return new SetCommand(getKey(), value, expiration, option); } + /** + * @return + */ public ByteBuffer getValue() { return value; } + /** + * @return + */ public Optional getExpiration() { return Optional.ofNullable(expiration); } + /** + * @return + */ public Optional getOption() { return Optional.ofNullable(option); } @@ -123,12 +177,12 @@ public interface ReactiveStringCommands { } /** - * Set each and every {@link KeyValue} item separately. + * Set each and every item separately by invoking {@link SetCommand}. * - * @param values must not be {@literal null}. - * @return {@link Flux} of {@link SetResponse} holding the {@link KeyValue} pair to set along with the command result. + * @param commands must not be {@literal null}. + * @return {@link Flux} of {@link BooleanResponse} holding the {@link SetCommand} along with the command result. */ - Flux> set(Publisher commands); + Flux> set(Publisher commands); /** * Get single element stored at {@literal key}. @@ -140,14 +194,15 @@ public interface ReactiveStringCommands { Assert.notNull(key, "Key must not be null!"); - return get(Mono.just(new KeyCommand(key))).next().map((result) -> result.getOutput()); + return get(Mono.just(new KeyCommand(key))).next().map(CommandResponse::getOutput); } /** * Get elements one by one. * * @param keys must not be {@literal null}. - * @return {@link Flux} of {@link GetResponse} holding the {@literal key} to get along with the value retrieved. + * @return {@link Flux} of {@link ByteBufferResponse} holding the {@literal key} to get along with the value + * retrieved. */ Flux> get(Publisher keys); @@ -169,13 +224,11 @@ public interface ReactiveStringCommands { /** * Set {@literal value} for {@literal key} and return the existing value one by one. * - * @param key must not be {@literal null}. - * @param value must not be {@literal null}. - * @return {@link Flux} of {@link GetSetResponse} holding the {@link KeyValue} pair to set along with the previously + * @param commands must not be {@literal null}. + * @return {@link Flux} of {@link ByteBufferResponse} holding the {@link SetCommand} along with the previously * existing value. */ - Flux> getSet( - Publisher command); + Flux> getSet(Publisher commands); /** * Get multiple values in one batch. @@ -191,15 +244,15 @@ public interface ReactiveStringCommands { } /** - * Get multiple values at in batches. + * Get multiple values at for {@literal keysets} in batches. * - * @param keys must not be {@literal null}. + * @param keysets must not be {@literal null}. * @return */ Flux, ByteBuffer>> mGet(Publisher> keysets); /** - * Set {@code value} for {@code key}, only if {@code key} does not exist. + * Set {@literal value} for {@literal key}, only if {@literal key} does not exist. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -207,22 +260,22 @@ public interface ReactiveStringCommands { */ default Mono setNX(ByteBuffer key, ByteBuffer value) { - Assert.notNull(key, "Keys must not be null!"); - Assert.notNull(value, "Keys must not be null!"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(value, "Value must not be null!"); return setNX(Mono.just(SetCommand.set(key).value(value))).next().map(BooleanResponse::getOutput); } /** - * Set {@code key value} pairs, only if {@code key} does not exist. + * Set {@literal key value} pairs, only if {@literal key} does not exist. * * @param values must not be {@literal null}. * @return */ - Flux> setNX(Publisher values); + Flux> setNX(Publisher values); /** - * Set {@code key value} pair and {@link Expiration}. + * Set {@literal key value} pair and {@link Expiration}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -233,23 +286,22 @@ public interface ReactiveStringCommands { Assert.notNull(key, "Keys must not be null!"); Assert.notNull(value, "Keys must not be null!"); - Assert.notNull(key, "ExpireTimeout must not be null!"); + Assert.notNull(expireTimeout, "ExpireTimeout must not be null!"); return setEX(Mono.just(SetCommand.set(key).value(value).expiring(expireTimeout))).next() .map(BooleanResponse::getOutput); } /** - * Set {@code key value} pairs and {@link Expiration}. + * Set {@literal key value} pairs and {@link Expiration}. * - * @param source must not be {@literal null}. - * @param expireTimeout must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ - Flux> setEX(Publisher command); + Flux> setEX(Publisher commands); /** - * Set {@code key value} pair and {@link Expiration}. + * Set {@literal key value} pair and {@link Expiration}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -267,15 +319,16 @@ public interface ReactiveStringCommands { } /** - * Set {@code key value} pairs and {@link Expiration}. + * Set {@literal key value} pairs and {@link Expiration}. * - * @param source must not be {@literal null}. - * @param expireTimeout must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ - Flux> pSetEX(Publisher command); + Flux> pSetEX(Publisher commands); /** + * {@code MSET} command parameters. + * * @author Christoph Strobl */ class MSetCommand implements Command { @@ -286,66 +339,82 @@ public interface ReactiveStringCommands { this.keyValuePairs = keyValuePairs; } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection.Command#getKey() + */ @Override public ByteBuffer getKey() { return null; } - public static ReactiveStringCommands.MSetCommand mset(Map keyValuePairs) { + /** + * Creates a new {@link MSetCommand} given a {@link Map} of key-value tuples. + * + * @param keyValuePairs must not be {@literal null}. + * @return a new {@link MSetCommand} for a {@link Map} of key-value tuples. + */ + public static MSetCommand mset(Map keyValuePairs) { + + Assert.notNull(keyValuePairs, "Key-value pairs must not be null!"); + return new MSetCommand(keyValuePairs); } + /** + * @return + */ public Map getKeyValuePairs() { return keyValuePairs; } } /** - * Set multiple keys to multiple values using key-value pairs provided in {@code tuple}. + * Set multiple keys to multiple values using key-value pairs provided in {@literal tuple}. * - * @param tuples must not be {@literal null}. + * @param keyValuePairs must not be {@literal null}. * @return */ - default Mono mSet(Map tuples) { + default Mono mSet(Map keyValuePairs) { - Assert.notNull(tuples, "Tuples must not be null!"); + Assert.notNull(keyValuePairs, "Key-value pairs must not be null!"); - return mSet(Mono.just(MSetCommand.mset(tuples))).next().map(BooleanResponse::getOutput); + return mSet(Mono.just(MSetCommand.mset(keyValuePairs))).next().map(BooleanResponse::getOutput); } /** - * Set multiple keys to multiple values using key-value pairs provided in {@code source}. + * Set multiple keys to multiple values using key-value pairs provided in {@literal commands}. + * + * @param commands must not be {@literal null}. + * @return + */ + Flux> mSet(Publisher commands); + + /** + * Set multiple keys to multiple values using key-value pairs provided in {@literal keyValuePairs} only if the + * provided key does not exist. + * + * @param keyValuePairs must not be {@literal null}. + * @return + */ + default Mono mSetNX(Map keyValuePairs) { + + Assert.notNull(keyValuePairs, "Key-value pairs must not be null!"); + + return mSetNX(Mono.just(MSetCommand.mset(keyValuePairs))).next().map(BooleanResponse::getOutput); + } + + /** + * Set multiple keys to multiple values using key-value pairs provided in {@literal tuples} only if the provided key + * does not exist. * * @param source must not be {@literal null}. * @return */ - Flux> mSet(Publisher source); + Flux> mSetNX(Publisher source); /** - * Set multiple keys to multiple values using key-value pairs provided in {@code tuples} only if the provided key does - * not exist. + * {@code APPEND} command parameters. * - * @param tuples must not be {@literal null}. - * @return - */ - default Mono mSetNX(Map tuples) { - - Assert.notNull(tuples, "Tuples must not be null!"); - - return mSetNX(Mono.just(MSetCommand.mset(tuples))).next().map(BooleanResponse::getOutput); - } - - /** - * Set multiple keys to multiple values using key-value pairs provided in {@code tuples} only if the provided key does - * not exist. - * - * @param source must not be {@literal null}. - * @return - */ - Flux> mSetNX( - Publisher source); - - /** * @author Christoph Strobl */ class AppendCommand extends KeyCommand { @@ -358,22 +427,43 @@ public interface ReactiveStringCommands { this.value = value; } - public static ReactiveStringCommands.AppendCommand key(ByteBuffer key) { + /** + * Creates a new {@link AppendCommand} given a {@literal key}. + * + * @param key must not be {@literal null}. + * @return a new {@link AppendCommand} for a {@literal key}. + */ + public static AppendCommand key(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new AppendCommand(key, null); } - public ReactiveStringCommands.AppendCommand append(ByteBuffer value) { + /** + * Applies the {@literal value} to append. Constructs a new command instance with all previously configured + * properties. + * + * @param value must not be {@literal null}. + * @return a new {@link AppendCommand} with {@literal value} applied. + */ + public AppendCommand append(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new AppendCommand(getKey(), value); } + /** + * @return + */ public ByteBuffer getValue() { return value; } - } /** - * Append a {@code value} to {@code key}. + * Append a {@literal value} to {@literal key}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -388,16 +478,15 @@ public interface ReactiveStringCommands { } /** - * Append a {@link KeyValue#value} to {@link KeyValue#key} + * Append a {@link AppendCommand#getValue()} to the {@link AppendCommand#getKey()}. * - * @param source must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ - Flux> append( - Publisher source); + Flux> append(Publisher commands); /** - * Get a substring of value of {@code key} between {@code begin} and {@code end}. + * Get a substring of value of {@literal key} between {@literal begin} and {@literal end}. * * @param key must not be {@literal null}. * @param begin @@ -408,21 +497,22 @@ public interface ReactiveStringCommands { Assert.notNull(key, "Key must not be null!"); - return getRange(Mono.just(RangeCommand.key(key).fromIndex(begin).toIndex(end))).next() + return getRange(Mono.just(RangeCommand.key(key).fromIndex(begin).toIndex(end))) // + .next() // .map(ByteBufferResponse::getOutput); } /** - * Get a substring of value of {@code key} between {@code begin} and {@code end}. + * Get a substring of value of {@literal key} between {@literal begin} and {@literal end}. * - * @param keys must not be {@literal null}. - * @param begin - * @param end + * @param commands must not be {@literal null}. * @return */ Flux> getRange(Publisher commands); /** + * {@code SETRANGE} command parameters. + * * @author Christoph Strobl */ class SetRangeCommand extends KeyCommand { @@ -437,29 +527,59 @@ public interface ReactiveStringCommands { this.offset = offset; } - public static ReactiveStringCommands.SetRangeCommand overwrite(ByteBuffer key) { + /** + * Creates a new {@link SetRangeCommand} given a {@literal key}. + * + * @param key must not be {@literal null}. + * @return a new {@link SetRangeCommand} for a {@literal key}. + */ + public static SetRangeCommand overwrite(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new SetRangeCommand(key, null, null); } - public ReactiveStringCommands.SetRangeCommand withValue(ByteBuffer value) { + /** + * Applies the {@literal value}. Constructs a new command instance with all previously configured properties. + * + * @param value must not be {@literal null}. + * @return a new {@link SetCommand} with {@literal value} applied. + */ + public SetRangeCommand withValue(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return new SetRangeCommand(getKey(), value, offset); } - public ReactiveStringCommands.SetRangeCommand atPosition(Long index) { + /** + * Applies the {@literal index}. Constructs a new command instance with all previously configured properties. + * + * @param index + * @return a new {@link SetRangeCommand} with {@literal key} applied. + */ + public SetRangeCommand atPosition(long index) { return new SetRangeCommand(getKey(), value, index); } + /** + * @return + */ public ByteBuffer getValue() { return value; } + /** + * @return + */ public Long getOffset() { return offset; } } /** - * Overwrite parts of {@code key} starting at the specified {@code offset} with given {@code value}. + * Overwrite parts of {@literal key} starting at the specified {@literal offset} with given {@literal value}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -476,40 +596,63 @@ public interface ReactiveStringCommands { } /** - * Overwrite parts of {@link KeyValue#key} starting at the specified {@code offset} with given {@link KeyValue#value}. + * Overwrite parts of {@link SetRangeCommand#key} starting at the specified {@literal offset} with given + * {@link SetRangeCommand#value}. * - * @param keys must not be {@literal null}. - * @param offset must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ - Flux> setRange( - Publisher commands); + Flux> setRange(Publisher commands); + /** + * {@code GETBIT} command parameters. + * + * @author Christoph Strobl + */ class GetBitCommand extends KeyCommand { - public Long offset; + private Long offset; - public GetBitCommand(ByteBuffer key, Long offset) { + private GetBitCommand(ByteBuffer key, Long offset) { super(key); + this.offset = offset; } - public static ReactiveStringCommands.GetBitCommand bit(ByteBuffer key) { + /** + * Creates a new {@link GetBitCommand} given a {@literal key}. + * + * @param key must not be {@literal null}. + * @return a new {@link GetBitCommand} for a {@literal key}. + */ + public static GetBitCommand bit(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new GetBitCommand(key, null); } - public ReactiveStringCommands.GetBitCommand atOffset(Long offset) { + /** + * Applies the offset {@literal index}. Constructs a new command instance with all previously configured properties. + * + * @param offset + * @return a new {@link GetBitCommand} with {@literal offset} applied. + */ + public GetBitCommand atOffset(long offset) { return new GetBitCommand(getKey(), offset); } + /** + * @return + */ public Long getOffset() { return offset; } } /** - * Get the bit value at {@code offset} of value at {@code key}. + * Get the bit value at {@literal offset} of value at {@literal key}. * * @param key must not be {@literal null}. * @param offset @@ -523,50 +666,81 @@ public interface ReactiveStringCommands { } /** - * Get the bit value at {@code offset} of value at {@code key}. + * Get the bit value at {@literal offset} of value at {@literal key}. * - * @param keys must not be {@literal null}. - * @param offset must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ - Flux> getBit( - Publisher commands); + Flux> getBit(Publisher commands); + /** + * {@code SETBIT} command parameters. + * + * @author Christoph Strobl + */ class SetBitCommand extends KeyCommand { private Long offset; - private Boolean value; + private boolean value; - private SetBitCommand(ByteBuffer key, Long offset, Boolean value) { + private SetBitCommand(ByteBuffer key, Long offset, boolean value) { super(key); + this.offset = offset; this.value = value; } - public static ReactiveStringCommands.SetBitCommand bit(ByteBuffer key) { - return new SetBitCommand(key, null, null); + /** + * Creates a new {@link SetBitCommand} given a {@literal key}. + * + * @param key must not be {@literal null}. + * @return a new {@link SetBitCommand} for a {@literal key}. + */ + public static SetBitCommand bit(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + + return new SetBitCommand(key, null, false); } - public ReactiveStringCommands.SetBitCommand atOffset(Long index) { - return new ReactiveStringCommands.SetBitCommand(getKey(), index, value); + /** + * Applies the offset {@literal index}. Constructs a new command instance with all previously configured properties. + * + * @param index + * @return a new {@link SetBitCommand} with {@literal offset} applied. + */ + public SetBitCommand atOffset(long index) { + return new SetBitCommand(getKey(), index, value); } - public ReactiveStringCommands.SetBitCommand to(Boolean bit) { - return new ReactiveStringCommands.SetBitCommand(getKey(), offset, bit); + /** + * Applies the {@literal bit}. Constructs a new command instance with all previously configured properties. + * + * @param bit + * @return a new {@link SetBitCommand} with {@literal offset} applied. + */ + public SetBitCommand to(boolean bit) { + return new SetBitCommand(getKey(), offset, bit); } + /** + * @return + */ public Long getOffset() { return offset; } - public Boolean getValue() { + /** + * @return + */ + public boolean getValue() { return value; } } /** - * Sets the bit at {@code offset} in value stored at {@code key} and return the original value. + * Sets the bit at {@literal offset} in value stored at {@literal key} and return the original value. * * @param key must not be {@literal null}. * @param offset @@ -581,59 +755,79 @@ public interface ReactiveStringCommands { } /** - * Sets the bit at {@code offset} in value stored at {@code key} and return the original value. + * Sets the bit at {@literal offset} in value stored at {@literal key} and return the original value. * - * @param keys must not be {@literal null}. - * @param offset must not be {@literal null}. - * @param value must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ - Flux> setBit( - Publisher commands); + Flux> setBit(Publisher commands); /** + * {@code BITCOUNT} command parameters. + * * @author Christoph Strobl */ class BitCountCommand extends KeyCommand { private Range range; - public BitCountCommand(ByteBuffer key, Range range) { + private BitCountCommand(ByteBuffer key, Range range) { super(key); + this.range = range; } - public static ReactiveStringCommands.BitCountCommand bitCount(ByteBuffer key) { - return new ReactiveStringCommands.BitCountCommand(key, null); + /** + * Creates a new {@link BitCountCommand} given a {@literal key}. + * + * @param key must not be {@literal null}. + * @return a new {@link BitCountCommand} for a {@literal key}. + */ + public static BitCountCommand bitCount(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + + return new BitCountCommand(key, null); } - public ReactiveStringCommands.BitCountCommand within(Range range) { - return new ReactiveStringCommands.BitCountCommand(getKey(), range); + /** + * Applies the {@link Range}. Constructs a new command instance with all previously configured properties. + * + * @param range must not be {@literal null}. + * @return a new {@link BitCountCommand} with {@link Range} applied. + */ + public BitCountCommand within(Range range) { + + Assert.notNull(range, "Range must not be null!"); + + return new BitCountCommand(getKey(), range); } + /** + * @return + */ public Range getRange() { return range; } - } /** - * Count the number of set bits (population counting) in value stored at {@code key}. + * Count the number of set bits (population counting) in value stored at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono bitCount(ByteBuffer key) { - Assert.notNull(key, "Key must not be null"); + Assert.notNull(key, "Key must not be null!"); return bitCount(Mono.just(BitCountCommand.bitCount(key))).next().map(NumericResponse::getOutput); } /** - * Count the number of set bits (population counting) of value stored at {@code key} between {@code begin} and - * {@code end}. + * Count the number of set bits (population counting) of value stored at {@literal key} between {@literal begin} and + * {@literal end}. * * @param key must not be {@literal null}. * @param begin @@ -642,25 +836,24 @@ public interface ReactiveStringCommands { */ default Mono bitCount(ByteBuffer key, long begin, long end) { - Assert.notNull(key, "Key must not be null"); + Assert.notNull(key, "Key must not be null!"); return bitCount(Mono.just(BitCountCommand.bitCount(key).within(new Range<>(begin, end)))).next() .map(NumericResponse::getOutput); } /** - * Count the number of set bits (population counting) of value stored at {@code key} between {@code begin} and - * {@code end}. + * Count the number of set bits (population counting) of value stored at {@literal key} between {@literal begin} and + * {@literal end}. * - * @param keys must not be {@literal null}. - * @param begin must not be {@literal null}. - * @param end must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ - Flux> bitCount( - Publisher commands); + Flux> bitCount(Publisher commands); /** + * {@code BITOP} command parameters. + * * @author Christoph Strobl */ class BitOpCommand { @@ -676,30 +869,67 @@ public interface ReactiveStringCommands { this.destinationKey = destinationKey; } - public static ReactiveStringCommands.BitOpCommand perform(BitOperation bitOp) { - return new ReactiveStringCommands.BitOpCommand(null, bitOp, null); + /** + * Creates a new {@link BitOpCommand} given a {@link BitOperation}. + * + * @param bitOp must not be {@literal null}. + * @return a new {@link BitCountCommand} for a {@link BitOperation}. + */ + public static BitOpCommand perform(BitOperation bitOp) { + + Assert.notNull(bitOp, "BitOperation must not be null!"); + + return new BitOpCommand(null, bitOp, null); } + /** + * Applies the operation to {@literal keys}. Constructs a new command instance with all previously configured + * properties. + * + * @param keys must not be {@literal null}. + * @return a new {@link BitOpCommand} with {@link Range} applied. + */ + public BitOpCommand onKeys(Collection keys) { + + Assert.notNull(keys, "Keys must not be null!"); + + return new BitOpCommand(new ArrayList<>(keys), bitOp, destinationKey); + } + + /** + * Applies the {@literal key} to store the result at. Constructs a new command instance with all previously + * configured properties. + * + * @param destinationKey must not be {@literal null}. + * @return a new {@link BitOpCommand} with {@link Range} applied. + */ + public BitOpCommand andSaveAs(ByteBuffer destinationKey) { + + Assert.notNull(destinationKey, "Destination key must not be null!"); + + return new BitOpCommand(keys, bitOp, destinationKey); + } + + /** + * @return + */ public BitOperation getBitOp() { return bitOp; } - public ReactiveStringCommands.BitOpCommand onKeys(List keys) { - return new ReactiveStringCommands.BitOpCommand(keys, bitOp, destinationKey); - } - + /** + * @return + */ public List getKeys() { return keys; } - public ReactiveStringCommands.BitOpCommand andSaveAs(ByteBuffer destinationKey) { - return new ReactiveStringCommands.BitOpCommand(keys, bitOp, destinationKey); - } - + /** + * @return + */ public ByteBuffer getDestinationKey() { return destinationKey; } - } /** @@ -710,40 +940,40 @@ public interface ReactiveStringCommands { * @param destination must not be {@literal null}. * @return */ - default Mono bitOp(List keys, BitOperation bitOp, ByteBuffer destination) { + default Mono bitOp(Collection keys, BitOperation bitOp, ByteBuffer destination) { - Assert.notNull(keys, "keys must not be null"); + Assert.notNull(keys, "Keys must not be null!"); + Assert.notNull(bitOp, "BitOperation must not be null!"); + Assert.notNull(destination, "Destination must not be null!"); - return bitOp(Mono.just(BitOpCommand.perform(bitOp).onKeys(keys).andSaveAs(destination))).next() + return bitOp(Mono.just(BitOpCommand.perform(bitOp).onKeys(keys).andSaveAs(destination))) // + .next() // .map(NumericResponse::getOutput); } /** * Perform bitwise operations between strings. * - * @param keys must not be {@literal null}. - * @param bitOp must not be {@literal null}. - * @param destination must not be {@literal null}. + * @param commands must not be {@literal null}. * @return */ - Flux> bitOp( - Publisher commands); + Flux> bitOp(Publisher commands); /** - * Get the length of the value stored at {@code key}. + * Get the length of the value stored at {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono strLen(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return strLen(Mono.just(new KeyCommand(key))).next().map(NumericResponse::getOutput); } /** - * Get the length of the value stored at {@code key}. + * Get the length of the value stored at {@literal key}. * * @param keys must not be {@literal null}. * @return diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java index 3aa1490d5..13a64d9e0 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java @@ -16,6 +16,8 @@ package org.springframework.data.redis.connection; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -31,12 +33,15 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.Numeric import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate; import org.springframework.data.redis.connection.RedisZSetCommands.Limit; import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; +import org.springframework.data.redis.util.ByteUtils; import org.springframework.util.Assert; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** + * Redis Sorted Set commands executed using reactive infrastructure. + * * @author Christoph Strobl * @author Mark Paluch * @since 2.0 @@ -44,71 +49,137 @@ import reactor.core.publisher.Mono; public interface ReactiveZSetCommands { /** + * {@code ZADD} command parameters. + * * @author Christoph Strobl */ class ZAddCommand extends KeyCommand { private final List tuples; - private final Boolean upsert; - private final Boolean returnTotalChanged; - private final Boolean incr; + private final boolean upsert; + private final boolean returnTotalChanged; + private final boolean incr; - private ZAddCommand(ByteBuffer key, List tuples, Boolean upsert, Boolean returnTotalChanged, Boolean incr) { + private ZAddCommand(ByteBuffer key, List tuples, boolean upsert, boolean returnTotalChanged, boolean incr) { super(key); + this.tuples = tuples; this.upsert = upsert; this.returnTotalChanged = returnTotalChanged; this.incr = incr; } + /** + * Creates a new {@link ZAddCommand} given a {@link Tuple}. + * + * @param tuple must not be {@literal null}. + * @return a new {@link ZAddCommand} for {@link Tuple}. + */ public static ZAddCommand tuple(Tuple tuple) { + + Assert.notNull(tuple, "Tuple must not be null!"); + return tuples(Collections.singletonList(tuple)); } - public static ZAddCommand tuples(List tuples) { - return new ZAddCommand(null, tuples, null, null, null); + /** + * Creates a new {@link ZAddCommand} given a {@link Collection} of {@link Tuple}. + * + * @param tuples must not be {@literal null}. + * @return a new {@link ZAddCommand} for {@link Tuple}. + */ + public static ZAddCommand tuples(Collection tuples) { + + Assert.notNull(tuples, "Tuples must not be null!"); + + return new ZAddCommand(null, new ArrayList<>(tuples), false, false, false); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZAddCommand} with {@literal key} applied. + */ public ZAddCommand to(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZAddCommand(key, tuples, upsert, returnTotalChanged, incr); } + /** + * Applies {@literal xx} mode (Only update elements that already exist. Never add elements). Constructs a new + * command instance with all previously configured properties. + * + * @return a new {@link ZAddCommand} with {@literal xx} applied. + */ public ZAddCommand xx() { return new ZAddCommand(getKey(), tuples, false, returnTotalChanged, incr); } + /** + * Applies {@literal nx} mode (Don't update already existing elements. Always add new elements). Constructs a new + * command instance with all previously configured properties. + * + * @return a new {@link ZAddCommand} with {@literal nx} applied. + */ public ZAddCommand nx() { return new ZAddCommand(getKey(), tuples, true, returnTotalChanged, incr); } + /** + * Applies {@literal ch} mode (Modify the return value from the number of new elements added, to the total number of + * elements changed). Constructs a new command instance with all previously configured properties. + * + * @return a new {@link ZAddCommand} with {@literal ch} applied. + */ public ZAddCommand ch() { return new ZAddCommand(getKey(), tuples, upsert, true, incr); } + /** + * Applies {@literal incr} mode (When this option is specified ZADD acts like ZINCRBY). Constructs a new command + * instance with all previously configured properties. + * + * @return a new {@link ZAddCommand} with {@literal incr} applied. + */ public ZAddCommand incr() { return new ZAddCommand(getKey(), tuples, upsert, upsert, true); } + /** + * @return + */ public List getTuples() { return tuples; } - public Optional getUpsert() { - return Optional.ofNullable(upsert); + /** + * @return + */ + public boolean isUpsert() { + return upsert; } - public Optional getIncr() { - return Optional.ofNullable(incr); + /** + * @return + */ + public boolean isIncr() { + return incr; } - public Optional getReturnTotalChanged() { - return Optional.ofNullable(returnTotalChanged); + /** + * @return + */ + public boolean isReturnTotalChanged() { + return returnTotalChanged; } } /** - * Add {@code value} to a sorted set at {@code key}, or update its {@code score} if it already exists. + * Add {@literal value} to a sorted set at {@literal key}, or update its {@literal score} if it already exists. * * @param key must not be {@literal null}. * @param score must not be {@literal null}. @@ -117,17 +188,17 @@ public interface ReactiveZSetCommands { */ default Mono zAdd(ByteBuffer key, Double score, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(score, "score must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(score, "Score must not be null!"); + Assert.notNull(value, "Value must not be null!"); - return zAdd(Mono.just(ZAddCommand.tuple(new DefaultTuple(value.array(), score)).to(key))).next() + return zAdd(Mono.just(ZAddCommand.tuple(new DefaultTuple(ByteUtils.getBytes(value), score)).to(key))).next() .map(resp -> resp.getOutput().longValue()); } /** - * Add {@link ZAddCommand#getTuple()} to a sorted set at {@link ZAddCommand#getKey()}, or update its {@code score} if - * it already exists. + * Add {@link ZAddCommand#getTuples()} to a sorted set at {@link ZAddCommand#getKey()}, or update its {@literal score} + * if it already exists. * * @param commands must not be {@literal null}. * @return @@ -135,6 +206,8 @@ public interface ReactiveZSetCommands { Flux> zAdd(Publisher commands); /** + * {@code ZREM} command parameters. + * * @author Christoph Strobl */ class ZRemCommand extends KeyCommand { @@ -144,43 +217,82 @@ public interface ReactiveZSetCommands { private ZRemCommand(ByteBuffer key, List values) { super(key); + this.values = values; } - public static ZRemCommand values(List values) { - return new ZRemCommand(null, values); + /** + * Creates a new {@link ZRemCommand} given a {@link Tuple}. + * + * @param value must not be {@literal null}. + * @return a new {@link ZAddCommand} for {@link Tuple}. + */ + public static ZRemCommand values(ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + + return new ZRemCommand(null, Collections.singletonList(value)); } + /** + * Creates a new {@link ZRemCommand} given a {@link Collection} of {@link Tuple}. + * + * @param values must not be {@literal null}. + * @return a new {@link ZAddCommand} for {@link Tuple}. + */ + public static ZRemCommand values(Collection values) { + + Assert.notNull(values, "Values must not be null!"); + + return new ZRemCommand(null, new ArrayList<>(values)); + } + + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZRemCommand} with {@literal key} applied. + */ public ZRemCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZRemCommand(key, values); } + /** + * @return + */ public List getValues() { return values; } } /** - * Remove {@code value} from sorted set. Return number of removed elements. + * Remove {@literal value} from sorted set. Return number of removed elements. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. * @return */ default Mono zRem(ByteBuffer key, ByteBuffer value) { + + Assert.notNull(value, "Value must not be null!"); + return zRem(key, Collections.singletonList(value)); } /** - * Remove {@code values} from sorted set. Return number of removed elements. + * Remove {@literal values} from sorted set. Return number of removed elements. * * @param key must not be {@literal null}. * @param values must not be {@literal null}. * @return */ - default Mono zRem(ByteBuffer key, List values) { + default Mono zRem(ByteBuffer key, Collection values) { - Assert.notNull(values, "values must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(values, "Values must not be null!"); return zRem(Mono.just(ZRemCommand.values(values).from(key))).next().map(NumericResponse::getOutput); } @@ -194,6 +306,8 @@ public interface ReactiveZSetCommands { Flux> zRem(Publisher commands); /** + * {@code ZINCRBY} command parameters. + * * @author Christoph Strobl */ class ZIncrByCommand extends KeyCommand { @@ -201,36 +315,71 @@ public interface ReactiveZSetCommands { private final ByteBuffer value; private final Number increment; - public ZIncrByCommand(ByteBuffer key, ByteBuffer value, Number increment) { + private ZIncrByCommand(ByteBuffer key, ByteBuffer value, Number increment) { super(key); + this.value = value; this.increment = increment; } + /** + * Creates a new {@link ZIncrByCommand} given a {@link ByteBuffer member}. + * + * @param member must not be {@literal null}. + * @return a new {@link ZAddCommand} for {@link Tuple}. + */ public static ZIncrByCommand scoreOf(ByteBuffer member) { + + Assert.notNull(member, "Member must not be null!"); + return new ZIncrByCommand(null, member, null); } + /** + * Applies the numeric {@literal increment}. Constructs a new command instance with all previously configured + * properties. + * + * @param increment must not be {@literal null}. + * @return a new {@link ZIncrByCommand} with {@literal increment} applied. + */ public ZIncrByCommand by(Number increment) { + + Assert.notNull(increment, "Increment must not be null!"); + return new ZIncrByCommand(getKey(), value, increment); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZIncrByCommand} with {@literal key} applied. + */ public ZIncrByCommand storedWithin(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZIncrByCommand(key, value, increment); } + /** + * @return + */ public ByteBuffer getValue() { return value; } + /** + * @return + */ public Number getIncrement() { return increment; } } /** - * Increment the score of element with {@code value} in sorted set by {@code increment}. + * Increment the score of element with {@literal value} in sorted set by {@literal increment}. * * @param key must not be {@literal null}. * @param increment must not be {@literal null}. @@ -239,9 +388,9 @@ public interface ReactiveZSetCommands { */ default Mono zIncrBy(ByteBuffer key, Number increment, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(increment, "increment must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(increment, "Increment must not be null!"); + Assert.notNull(value, "Value must not be null!"); return zIncrBy(Mono.just(ZIncrByCommand.scoreOf(value).by(increment).storedWithin(key))).next() .map(NumericResponse::getOutput); @@ -257,6 +406,8 @@ public interface ReactiveZSetCommands { Flux> zIncrBy(Publisher commands); /** + * {@code ZRANK}/{@literal ZREVRANK} command parameters. + * * @author Christoph Strobl */ class ZRankCommand extends KeyCommand { @@ -267,33 +418,68 @@ public interface ReactiveZSetCommands { private ZRankCommand(ByteBuffer key, ByteBuffer value, Direction direction) { super(key); + this.value = value; this.direction = direction; } + /** + * Creates a new {@link ZRankCommand} given a {@link ByteBuffer member} to obtain its rank (ordering low to high). + * + * @param member must not be {@literal null}. + * @return a new {@link ZRankCommand} for {@link Tuple}. + */ public static ZRankCommand indexOf(ByteBuffer member) { + + Assert.notNull(member, "Member must not be null!"); + return new ZRankCommand(null, member, Direction.ASC); } + /** + * Creates a new {@link ZIncrByCommand} given a {@link ByteBuffer member} to obtain its reversed rank (ordering high + * to low). + * + * @param member must not be {@literal null}. + * @return a new {@link ZRankCommand} for {@link Tuple}. + */ public static ZRankCommand reverseIndexOf(ByteBuffer member) { + + Assert.notNull(member, "Member must not be null!"); + return new ZRankCommand(null, member, Direction.DESC); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZRankCommand} with {@literal key} applied. + */ public ZRankCommand storedWithin(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZRankCommand(key, value, direction); } + /** + * @return + */ public ByteBuffer getValue() { return value; } + /** + * @return + */ public Direction getDirection() { return direction; } } /** - * Determine the index of element with {@code value} in a sorted set. + * Determine the index of element with {@literal value} in a sorted set. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -301,14 +487,14 @@ public interface ReactiveZSetCommands { */ default Mono zRank(ByteBuffer key, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(value, "Value must not be null!"); return zRank(Mono.just(ZRankCommand.indexOf(value).storedWithin(key))).next().map(NumericResponse::getOutput); } /** - * Determine the index of element with {@code value} in a sorted set when scored high to low. + * Determine the index of element with {@literal value} in a sorted set when scored high to low. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -316,15 +502,15 @@ public interface ReactiveZSetCommands { */ default Mono zRevRank(ByteBuffer key, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(value, "Value must not be null!"); return zRank(Mono.just(ZRankCommand.reverseIndexOf(value).storedWithin(key))).next() .map(NumericResponse::getOutput); } /** - * Determine the index of element with {@code value} in a sorted set when scored by + * Determine the index of element with {@literal value} in a sorted set when scored by * {@link ZRankCommand#getDirection()}. * * @param commands must not be {@literal null}. @@ -333,52 +519,100 @@ public interface ReactiveZSetCommands { Flux> zRank(Publisher commands); /** + * {@code ZRANGE}/{@literal ZREVRANGE} command parameters. + * * @author Christoph Strobl */ class ZRangeCommand extends KeyCommand { private final Range range; - private final Boolean withScores; + private final boolean withScores; private final Direction direction; - public ZRangeCommand(ByteBuffer key, Range range, Direction direction, Boolean withScores) { + private ZRangeCommand(ByteBuffer key, Range range, Direction direction, boolean withScores) { + super(key); + this.range = range; this.withScores = withScores; this.direction = direction; } - public static ZRangeCommand reverseValuesWithin(Range range) { - return new ZRangeCommand(null, range, Direction.DESC, null); - } - + /** + * Creates a new {@link ZRangeCommand} given a {@link Range} to obtain elements ordered from the lowest to the + * highest score. + * + * @param range must not be {@literal null}. + * @return a new {@link ZRangeCommand} for {@link Tuple}. + */ public static ZRangeCommand valuesWithin(Range range) { - return new ZRangeCommand(null, range, Direction.ASC, null); + + Assert.notNull(range, "Range must not be null!"); + + return new ZRangeCommand(null, range, Direction.ASC, false); } + /** + * Creates a new {@link ZRangeCommand} given a {@link Range} to obtain elements ordered from the highest to the + * lowest score. + * + * @param range must not be {@literal null}. + * @return a new {@link ZRangeCommand} for {@link Tuple}. + */ + public static ZRangeCommand reverseValuesWithin(Range range) { + + Assert.notNull(range, "Range must not be null!"); + + return new ZRangeCommand(null, range, Direction.DESC, false); + } + + /** + * Return the score along with each returned element. Constructs a new command instance with all previously + * configured properties. + * + * @return a new {@link ZRangeCommand} with score retrieval applied. + */ public ZRangeCommand withScores() { - return new ZRangeCommand(getKey(), range, direction, Boolean.TRUE); + return new ZRangeCommand(getKey(), range, direction, true); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZRangeCommand} with {@literal key} applied. + */ public ZRangeCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZRangeCommand(key, range, direction, withScores); } + /** + * @return + */ public Range getRange() { return range; } - public Optional getWithScores() { - return Optional.ofNullable(withScores); + /** + * @return + */ + public boolean isWithScores() { + return withScores; } + /** + * @return + */ public Direction getDirection() { return direction; } } /** - * Get elements in {@code range} from sorted set. + * Get elements in {@literal range} from sorted set. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -386,14 +620,19 @@ public interface ReactiveZSetCommands { */ default Mono> zRange(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); - return zRange(Mono.just(ZRangeCommand.valuesWithin(range).from(key))).next().map( - resp -> resp.getOutput().stream().map(tuple -> ByteBuffer.wrap(tuple.getValue())).collect(Collectors.toList())); + return zRange(Mono.just(ZRangeCommand.valuesWithin(range).from(key))) // + .next() // + .map(resp -> resp.getOutput() // + .stream() // + .map(tuple -> ByteBuffer.wrap(tuple.getValue())) // + .collect(Collectors.toList())); } /** - * Get set of {@link Tuple}s in {@code range} from sorted set. + * Get set of {@link Tuple}s in {@literal range} from sorted set. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -401,14 +640,14 @@ public interface ReactiveZSetCommands { */ default Mono> zRangeWithScores(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return zRange(Mono.just(ZRangeCommand.valuesWithin(range).withScores().from(key))).next() .map(MultiValueResponse::getOutput); } /** - * Get elements in {@code range} from sorted set in reverse {@code score} ordering. + * Get elements in {@literal range} from sorted set in reverse {@literal score} ordering. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -416,14 +655,14 @@ public interface ReactiveZSetCommands { */ default Mono> zRevRange(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return zRange(Mono.just(ZRangeCommand.reverseValuesWithin(range).from(key))).next().map( resp -> resp.getOutput().stream().map(tuple -> ByteBuffer.wrap(tuple.getValue())).collect(Collectors.toList())); } /** - * Get set of {@link Tuple}s in {@code range} from sorted set in reverse {@code score} ordering. + * Get set of {@link Tuple}s in {@literal range} from sorted set in reverse {@literal score} ordering. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -431,14 +670,14 @@ public interface ReactiveZSetCommands { */ default Mono> zRevRangeWithScores(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return zRange(Mono.just(ZRangeCommand.reverseValuesWithin(range).withScores().from(key))).next() .map(MultiValueResponse::getOutput); } /** - * Get set of {@link Tuple}s in {@code range} from sorted set. + * Get set of {@link Tuple}s in {@literal range} from sorted set. * * @param commands must not be {@literal null}. * @return @@ -446,64 +685,120 @@ public interface ReactiveZSetCommands { Flux> zRange(Publisher commands); /** + * {@literal ZRANGEBYSCORE}/{@literal ZREVRANGEBYSCORE}. + * * @author Christoph Strobl */ class ZRangeByScoreCommand extends KeyCommand { private final Range range; - private final Boolean withScores; + private final boolean withScores; private final Direction direction; private final Limit limit; - private ZRangeByScoreCommand(ByteBuffer key, Range range, Direction direction, Boolean withScores, + private ZRangeByScoreCommand(ByteBuffer key, Range range, Direction direction, boolean withScores, Limit limit) { super(key); + this.range = range; this.withScores = withScores; this.direction = direction; this.limit = limit; } - public static ZRangeByScoreCommand reverseScoresWithin(Range range) { - return new ZRangeByScoreCommand(null, range, Direction.DESC, null, null); - } - + /** + * Creates a new {@link ZRangeByScoreCommand} given a {@link Range} to obtain elements ordered from the lowest to + * the highest score. + * + * @param range must not be {@literal null}. + * @return a new {@link ZRangeByScoreCommand} for {@link Tuple}. + */ public static ZRangeByScoreCommand scoresWithin(Range range) { - return new ZRangeByScoreCommand(null, range, Direction.ASC, null, null); + + Assert.notNull(range, "Range must not be null!"); + + return new ZRangeByScoreCommand(null, range, Direction.ASC, false, null); } + /** + * Creates a new {@link ZRangeByScoreCommand} given a {@link Range} to obtain elements ordered from the highest to + * the lowest score. + * + * @param range must not be {@literal null}. + * @return a new {@link ZRangeByScoreCommand} for {@link Tuple}. + */ + public static ZRangeByScoreCommand reverseScoresWithin(Range range) { + + Assert.notNull(range, "Range must not be null!"); + + return new ZRangeByScoreCommand(null, range, Direction.DESC, false, null); + } + + /** + * Return the score along with each returned element. Constructs a new command instance with all previously + * configured properties. + * + * @return a new {@link ZRangeByScoreCommand} with score retrieval applied. + */ public ZRangeByScoreCommand withScores() { - return new ZRangeByScoreCommand(getKey(), range, direction, Boolean.TRUE, limit); + return new ZRangeByScoreCommand(getKey(), range, direction, true, limit); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZRangeByScoreCommand} with {@literal key} applied. + */ public ZRangeByScoreCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZRangeByScoreCommand(key, range, direction, withScores, limit); } + /** + * Applies the {@link Limit}. Constructs a new command instance with all previously configured properties. + * + * @param limit can be {@literal null}. + * @return a new {@link ZRangeByScoreCommand} with {@link Limit} applied. + */ public ZRangeByScoreCommand limitTo(Limit limit) { return new ZRangeByScoreCommand(getKey(), range, direction, withScores, limit); } + /** + * @return + */ public Range getRange() { return range; } - public Optional getWithScores() { - return Optional.ofNullable(withScores); + /** + * @return + */ + public boolean isWithScores() { + return withScores; } + /** + * @return + */ public Direction getDirection() { return direction; } + /** + * @return + */ public Optional getLimit() { return Optional.ofNullable(limit); } } /** - * Get elements in {@code range} from sorted set. + * Get elements in {@literal range} from sorted set. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -511,14 +806,19 @@ public interface ReactiveZSetCommands { */ default Mono> zRangeByScore(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); - return zRangeByScore(Mono.just(ZRangeByScoreCommand.scoresWithin(range).from(key))).next().map( - resp -> resp.getOutput().stream().map(tuple -> ByteBuffer.wrap(tuple.getValue())).collect(Collectors.toList())); + return zRangeByScore(Mono.just(ZRangeByScoreCommand.scoresWithin(range).from(key))) // + .next() // + .map(resp -> resp.getOutput() // + .stream() // + .map(tuple -> ByteBuffer.wrap(tuple.getValue())) // + .collect(Collectors.toList())); } /** - * Get elements in {@code range} from sorted set. + * Get elements in {@literal range} from sorted set. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -527,15 +827,19 @@ public interface ReactiveZSetCommands { */ default Mono> zRangeByScore(ByteBuffer key, Range range, Limit limit) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); - return zRangeByScore(Mono.just(ZRangeByScoreCommand.scoresWithin(range).from(key).limitTo(limit))).next().map( - resp -> resp.getOutput().stream().map(tuple -> ByteBuffer.wrap(tuple.getValue())).collect(Collectors.toList())); + return zRangeByScore(Mono.just(ZRangeByScoreCommand.scoresWithin(range).from(key).limitTo(limit))) // + .next() // + .map(resp -> resp.getOutput() // + .stream() // + .map(tuple -> ByteBuffer.wrap(tuple.getValue())) // + .collect(Collectors.toList())); } /** - * Get set of {@link Tuple}s in {@code range} from sorted set. + * Get {@link Tuple}s in {@literal range} from sorted set. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -543,15 +847,15 @@ public interface ReactiveZSetCommands { */ default Mono> zRangeByScoreWithScores(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); return zRangeByScore(Mono.just(ZRangeByScoreCommand.scoresWithin(range).withScores().from(key))).next() .map(MultiValueResponse::getOutput); } /** - * Get set of {@link Tuple}s in {@code range} from sorted set. + * Get {@link Tuple}s in {@literal range} from sorted set. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -560,15 +864,15 @@ public interface ReactiveZSetCommands { */ default Mono> zRangeByScoreWithScores(ByteBuffer key, Range range, Limit limit) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); return zRangeByScore(Mono.just(ZRangeByScoreCommand.scoresWithin(range).withScores().from(key).limitTo(limit))) .next().map(MultiValueResponse::getOutput); } /** - * Get elements in {@code range} from sorted set in reverse {@code score} ordering. + * Get elements in {@literal range} from sorted set in reverse {@literal score} ordering. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -576,14 +880,18 @@ public interface ReactiveZSetCommands { */ default Mono> zRevRangeByScore(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); - return zRangeByScore(Mono.just(ZRangeByScoreCommand.reverseScoresWithin(range).from(key))).next().map( - resp -> resp.getOutput().stream().map(tuple -> ByteBuffer.wrap(tuple.getValue())).collect(Collectors.toList())); + return zRangeByScore(Mono.just(ZRangeByScoreCommand.reverseScoresWithin(range).from(key))) // + .next() // + .map(resp -> resp.getOutput() // + .stream() // + .map(tuple -> ByteBuffer.wrap(tuple.getValue())) // + .collect(Collectors.toList())); } /** - * Get elements in {@code range} from sorted set in reverse {@code score} ordering. + * Get elements in {@literal range} from sorted set in reverse {@literal score} ordering. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -592,16 +900,17 @@ public interface ReactiveZSetCommands { */ default Mono> zRevRangeByScore(ByteBuffer key, Range range, Limit limit) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); - return zRangeByScore(Mono.just(ZRangeByScoreCommand.reverseScoresWithin(range).from(key).limitTo(limit))).next() - .map(resp -> resp.getOutput().stream().map(tuple -> ByteBuffer.wrap(tuple.getValue())) - .collect(Collectors.toList())); + return zRangeByScore(Mono.just(ZRangeByScoreCommand.reverseScoresWithin(range).from(key).limitTo(limit))) // + .next() // + .map(resp -> resp.getOutput() // + .stream().map(tuple -> ByteBuffer.wrap(tuple.getValue())).collect(Collectors.toList())); } /** - * Get set of {@link Tuple}s in {@code range} from sorted set in reverse {@code score} ordering. + * Get set of {@link Tuple}s in {@literal range} from sorted set in reverse {@literal score} ordering. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -609,15 +918,15 @@ public interface ReactiveZSetCommands { */ default Mono> zRevRangeByScoreWithScores(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); return zRangeByScore(Mono.just(ZRangeByScoreCommand.reverseScoresWithin(range).withScores().from(key))).next() .map(MultiValueResponse::getOutput); } /** - * Get set of {@link Tuple}s in {@code range} from sorted set in reverse {@code score} ordering. + * Get {@link Tuple}s in {@literal range} from sorted set in reverse {@literal score} ordering. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -626,8 +935,8 @@ public interface ReactiveZSetCommands { */ default Mono> zRevRangeByScoreWithScores(ByteBuffer key, Range range, Limit limit) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); return zRangeByScore( Mono.just(ZRangeByScoreCommand.reverseScoresWithin(range).withScores().from(key).limitTo(limit))).next() @@ -635,7 +944,7 @@ public interface ReactiveZSetCommands { } /** - * Get set of {@link Tuple}s in {@code range} from sorted set. + * Get {@link Tuple}s in {@literal range} from sorted set. * * @param commands must not be {@literal null}. * @return @@ -643,6 +952,8 @@ public interface ReactiveZSetCommands { Flux> zRangeByScore(Publisher commands); /** + * {@code ZCOUNT} command parameters. + * * @author Christoph Strobl */ class ZCountCommand extends KeyCommand { @@ -655,24 +966,44 @@ public interface ReactiveZSetCommands { this.range = range; } + /** + * Creates a new {@link ZCountCommand} given a {@link Range}. + * + * @param range must not be {@literal null}. + * @return a new {@link ZCountCommand} for {@link Range}. + */ public static ZCountCommand scoresWithin(Range range) { + + Assert.notNull(range, "Range must not be null!"); + return new ZCountCommand(null, range); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZCountCommand} with {@literal key} applied. + */ public ZCountCommand forKey(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZCountCommand(key, range); } + /** + * @return + */ public Range getRange() { return range; } - } /** * Count number of elements within sorted set with scores within {@link Range}.
- * NOTE please use {@link Double#NEGATIVE_INFINITY} for {@code -inf} and {@link Double#POSITIVE_INFINITY} for - * {@code +inf}. + * NOTE please use {@link Double#NEGATIVE_INFINITY} for {@literal -inf} and {@link Double#POSITIVE_INFINITY} + * for {@literal +inf}. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -680,16 +1011,16 @@ public interface ReactiveZSetCommands { */ default Mono zCount(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); return zCount(Mono.just(ZCountCommand.scoresWithin(range).forKey(key))).next().map(NumericResponse::getOutput); } /** * Count number of elements within sorted set with scores within {@link Range}.
- * NOTE please use {@link Double#NEGATIVE_INFINITY} for {@code -inf} and {@link Double#POSITIVE_INFINITY} for - * {@code +inf}. + * NOTE please use {@link Double#NEGATIVE_INFINITY} for {@literal -inf} and {@link Double#POSITIVE_INFINITY} + * for {@literal +inf}. * * @param commands must not be {@literal null}. * @return @@ -697,14 +1028,14 @@ public interface ReactiveZSetCommands { Flux> zCount(Publisher commands); /** - * Get the size of sorted set with {@code key}. + * Get the size of sorted set with {@literal key}. * * @param key must not be {@literal null}. * @return */ default Mono zCard(ByteBuffer key) { - Assert.notNull(key, "key must not be null"); + Assert.notNull(key, "Key must not be null!"); return zCard(Mono.just(new KeyCommand(key))).next().map(NumericResponse::getOutput); } @@ -718,6 +1049,8 @@ public interface ReactiveZSetCommands { Flux> zCard(Publisher commands); /** + * {@code ZSCORE} command parameters. + * * @author Christoph Strobl */ class ZScoreCommand extends KeyCommand { @@ -730,22 +1063,42 @@ public interface ReactiveZSetCommands { this.value = value; } + /** + * Creates a new {@link ZScoreCommand} given a {@link ByteBuffer member}. + * + * @param member must not be {@literal null}. + * @return a new {@link ZScoreCommand} for {@link Range}. + */ public static ZScoreCommand scoreOf(ByteBuffer member) { + + Assert.notNull(member, "Member must not be null!"); + return new ZScoreCommand(null, member); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZScoreCommand} with {@literal key} applied. + */ public ZScoreCommand forKey(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZScoreCommand(key, value); } + /** + * @return + */ public ByteBuffer getValue() { return value; } - } /** - * Get the score of element with {@code value} from sorted set with key {@code key}. + * Get the score of element with {@literal value} from sorted set with key {@literal key}. * * @param key must not be {@literal null}. * @param value must not be {@literal null}. @@ -753,8 +1106,8 @@ public interface ReactiveZSetCommands { */ default Mono zScore(ByteBuffer key, ByteBuffer value) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(value, "value must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(value, "Value must not be null!"); return zScore(Mono.just(ZScoreCommand.scoreOf(value).forKey(key))).next().map(NumericResponse::getOutput); } @@ -769,6 +1122,8 @@ public interface ReactiveZSetCommands { Flux> zScore(Publisher commands); /** + * {@code ZREMRANGEBYRANK} command parameters. + * * @author Christoph Strobl */ class ZRemRangeByRankCommand extends KeyCommand { @@ -780,21 +1135,42 @@ public interface ReactiveZSetCommands { this.range = range; } + /** + * Creates a new {@link ZRemRangeByRankCommand} given a {@link Range}. + * + * @param range must not be {@literal null}. + * @return a new {@link ZRemRangeByRankCommand} for {@link Range}. + */ public static ZRemRangeByRankCommand valuesWithin(Range range) { + + Assert.notNull(range, "Range must not be null!"); + return new ZRemRangeByRankCommand(null, range); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZRemRangeByRankCommand} with {@literal key} applied. + */ public ZRemRangeByRankCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZRemRangeByRankCommand(key, range); } + /** + * @return + */ public Range getRange() { return range; } } /** - * Remove elements in {@link Range} from sorted set with {@code key}. + * Remove elements in {@link Range} from sorted set with {@literal key}. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -802,8 +1178,8 @@ public interface ReactiveZSetCommands { */ default Mono zRemRangeByRank(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); return zRemRangeByRank(Mono.just(ZRemRangeByRankCommand.valuesWithin(range).from(key))).next() .map(NumericResponse::getOutput); @@ -818,6 +1194,8 @@ public interface ReactiveZSetCommands { Flux> zRemRangeByRank(Publisher commands); /** + * {@code ZREMRANGEBYSCORE} command parameters. + * * @author Christoph Strobl */ class ZRemRangeByScoreCommand extends KeyCommand { @@ -830,22 +1208,39 @@ public interface ReactiveZSetCommands { this.range = range; } + /** + * Creates a new {@link ZRemRangeByScoreCommand} given a {@link Range}. + * + * @param range must not be {@literal null}. + * @return a new {@link ZRemRangeByScoreCommand} for {@link Range}. + */ public static ZRemRangeByScoreCommand scoresWithin(Range range) { return new ZRemRangeByScoreCommand(null, range); } + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZRemRangeByRankCommand} with {@literal key} applied. + */ public ZRemRangeByScoreCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZRemRangeByScoreCommand(key, range); } + /** + * @return + */ public Range getRange() { return range; } - } /** - * Remove elements in {@link Range} from sorted set with {@code key}. + * Remove elements in {@link Range} from sorted set with {@literal key}. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -853,8 +1248,8 @@ public interface ReactiveZSetCommands { */ default Mono zRemRangeByScore(ByteBuffer key, Range range) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); return zRemRangeByScore(Mono.just(ZRemRangeByScoreCommand.scoresWithin(range).from(key))).next() .map(NumericResponse::getOutput); @@ -869,6 +1264,8 @@ public interface ReactiveZSetCommands { Flux> zRemRangeByScore(Publisher commands); /** + * {@code ZUNIONSTORE} command parameters. + * * @author Christoph Strobl */ class ZUnionStoreCommand extends KeyCommand { @@ -885,41 +1282,78 @@ public interface ReactiveZSetCommands { this.aggregateFunction = aggregate; } + /** + * Creates a new {@link ZUnionStoreCommand} given a {@link List} of keys. + * + * @param keys must not be {@literal null}. + * @return a new {@link ZUnionStoreCommand} for {@link Range}. + */ public static ZUnionStoreCommand sets(List keys) { - return new ZUnionStoreCommand(null, keys, null, null); + + Assert.notNull(keys, "Keys must not be null!"); + + return new ZUnionStoreCommand(null, new ArrayList<>(keys), null, null); } + /** + * Applies the {@link List} of weights. Constructs a new command instance with all previously configured properties. + * + * @param weights must not be {@literal null}. + * @return a new {@link ZUnionStoreCommand} with {@literal weights} applied. + */ public ZUnionStoreCommand applyWeights(List weights) { return new ZUnionStoreCommand(getKey(), sourceKeys, weights, aggregateFunction); } + /** + * Applies a specific {@link Aggregate} function. Constructs a new command instance with all previously configured + * properties. + * + * @param aggregateFunction can be {@literal null}. + * @return a new {@link ZUnionStoreCommand} with {@link Aggregate} applied. + */ public ZUnionStoreCommand aggregateUsing(Aggregate aggregateFunction) { return new ZUnionStoreCommand(getKey(), sourceKeys, weights, aggregateFunction); } + /** + * Applies the {@literal key} at which the result is stored. Constructs a new command instance with all previously + * configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZUnionStoreCommand} with {@literal key} applied. + */ public ZUnionStoreCommand storeAs(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZUnionStoreCommand(key, sourceKeys, weights, aggregateFunction); } + /** + * @return + */ public List getSourceKeys() { return sourceKeys; } + /** + * @return + */ public List getWeights() { return weights == null ? Collections.emptyList() : weights; } + /** + * @return + */ public Optional getAggregateFunction() { return Optional.ofNullable(aggregateFunction); } - - public Integer getNumKeys() { - return sourceKeys != null ? sourceKeys.size() : null; - } } /** - * Union sorted {@code sets} and store result in destination {@code destinationKey}. + * Union sorted {@literal sets} and store result in destination {@literal destinationKey}. * * @param destinationKey must not be {@literal null}. * @param sets must not be {@literal null}. @@ -930,8 +1364,8 @@ public interface ReactiveZSetCommands { } /** - * Union sorted {@code sets} and store result in destination {@code destinationKey} and apply weights to individual - * sets. + * Union sorted {@literal sets} and store result in destination {@literal destinationKey} and apply weights to + * individual sets. * * @param destinationKey must not be {@literal null}. * @param sets must not be {@literal null}. @@ -943,8 +1377,8 @@ public interface ReactiveZSetCommands { } /** - * Union sorted {@code sets} by applying {@code aggregateFunction} and store result in destination - * {@code destinationKey} and apply weights to individual sets. + * Union sorted {@literal sets} by applying {@literal aggregateFunction} and store result in destination + * {@literal destinationKey} and apply weights to individual sets. * * @param destinationKey must not be {@literal null}. * @param sets must not be {@literal null}. @@ -955,8 +1389,8 @@ public interface ReactiveZSetCommands { default Mono zUnionStore(ByteBuffer destinationKey, List sets, List weights, Aggregate aggregateFunction) { - Assert.notNull(destinationKey, "destinationKey must not be null"); - Assert.notNull(sets, "sets must not be null"); + Assert.notNull(destinationKey, "DestinationKey must not be null!"); + Assert.notNull(sets, "Sets must not be null!"); return zUnionStore(Mono.just( ZUnionStoreCommand.sets(sets).aggregateUsing(aggregateFunction).applyWeights(weights).storeAs(destinationKey))) @@ -964,8 +1398,8 @@ public interface ReactiveZSetCommands { } /** - * Union sorted {@code sets} by applying {@code aggregateFunction} and store result in destination - * {@code destinationKey} and apply weights to individual sets. + * Union sorted {@literal sets} by applying {@literal aggregateFunction} and store result in destination + * {@literal destinationKey} and apply weights to individual sets. * * @param commands * @return @@ -973,6 +1407,8 @@ public interface ReactiveZSetCommands { Flux> zUnionStore(Publisher commands); /** + * {@code ZINTERSTORE} command parameters. + * * @author Christoph Strobl */ class ZInterStoreCommand extends KeyCommand { @@ -989,41 +1425,79 @@ public interface ReactiveZSetCommands { this.aggregateFunction = aggregate; } + /** + * Creates a new {@link ZInterStoreCommand} given a {@link List} of keys. + * + * @param keys must not be {@literal null}. + * @return a new {@link ZInterStoreCommand} for {@link Range}. + */ public static ZInterStoreCommand sets(List keys) { - return new ZInterStoreCommand(null, keys, null, null); + + Assert.notNull(keys, "Keys must not be null!"); + + return new ZInterStoreCommand(null, new ArrayList<>(keys), null, null); } + /** + * Applies the {@link Collection} of weights. Constructs a new command instance with all previously configured + * properties. + * + * @param weights must not be {@literal null}. + * @return a new {@link ZInterStoreCommand} with {@literal weights} applied. + */ public ZInterStoreCommand applyWeights(List weights) { return new ZInterStoreCommand(getKey(), sourceKeys, weights, aggregateFunction); } + /** + * Applies a specific {@link Aggregate} function. Constructs a new command instance with all previously configured + * properties. + * + * @param aggregateFunction can be {@literal null}. + * @return a new {@link ZInterStoreCommand} with {@link Aggregate} applied. + */ public ZInterStoreCommand aggregateUsing(Aggregate aggregateFunction) { return new ZInterStoreCommand(getKey(), sourceKeys, weights, aggregateFunction); } + /** + * Applies the {@literal key} at which the result is stored. Constructs a new command instance with all previously + * configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZInterStoreCommand} with {@literal key} applied. + */ public ZInterStoreCommand storeAs(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZInterStoreCommand(key, sourceKeys, weights, aggregateFunction); } + /** + * @return + */ public List getSourceKeys() { return sourceKeys; } + /** + * @return + */ public List getWeights() { return weights == null ? Collections.emptyList() : weights; } + /** + * @return + */ public Optional getAggregateFunction() { return Optional.ofNullable(aggregateFunction); } - - public Integer getNumKeys() { - return sourceKeys != null ? sourceKeys.size() : null; - } } /** - * Intersect sorted {@code sets} and store result in destination {@code destinationKey}. + * Intersect sorted {@literal sets} and store result in destination {@literal destinationKey}. * * @param destinationKey must not be {@literal null}. * @param sets must not be {@literal null}. @@ -1034,7 +1508,7 @@ public interface ReactiveZSetCommands { } /** - * Intersect sorted {@code sets} and store result in destination {@code destinationKey} and apply weights to + * Intersect sorted {@literal sets} and store result in destination {@literal destinationKey} and apply weights to * individual sets. * * @param destinationKey must not be {@literal null}. @@ -1047,8 +1521,8 @@ public interface ReactiveZSetCommands { } /** - * Intersect sorted {@code sets} by applying {@code aggregateFunction} and store result in destination - * {@code destinationKey} and apply weights to individual sets. + * Intersect sorted {@literal sets} by applying {@literal aggregateFunction} and store result in destination + * {@literal destinationKey} and apply weights to individual sets. * * @param destinationKey must not be {@literal null}. * @param sets must not be {@literal null}. @@ -1059,8 +1533,8 @@ public interface ReactiveZSetCommands { default Mono zInterStore(ByteBuffer destinationKey, List sets, List weights, Aggregate aggregateFunction) { - Assert.notNull(destinationKey, "destinationKey must not be null"); - Assert.notNull(sets, "sets must not be null"); + Assert.notNull(destinationKey, "DestinationKey must not be null!"); + Assert.notNull(sets, "Sets must not be null!"); return zInterStore(Mono.just( ZInterStoreCommand.sets(sets).aggregateUsing(aggregateFunction).applyWeights(weights).storeAs(destinationKey))) @@ -1068,8 +1542,8 @@ public interface ReactiveZSetCommands { } /** - * Intersect sorted {@code sets} by applying {@code aggregateFunction} and store result in destination - * {@code destinationKey} and apply weights to individual sets. + * Intersect sorted {@literal sets} by applying {@literal aggregateFunction} and store result in destination + * {@literal destinationKey} and apply weights to individual sets. * * @param commands * @return @@ -1077,6 +1551,8 @@ public interface ReactiveZSetCommands { Flux> zInterStore(Publisher commands); /** + * {@code ZRANGEBYLEX}/{@literal ZREVRANGEBYLEX} command parameters. + * * @author Christoph Strobl */ class ZRangeByLexCommand extends KeyCommand { @@ -1093,37 +1569,81 @@ public interface ReactiveZSetCommands { this.limit = limit; } - public static ZRangeByLexCommand reverseStringsWithin(Range range) { - return new ZRangeByLexCommand(null, range, Direction.DESC, null); - } - + /** + * Creates a new {@link ZRangeByLexCommand} given a {@link Range} of {@link String} to retrieve elements + * lexicographical ordering. + * + * @param range must not be {@literal null}. + * @return a new {@link ZRangeByLexCommand} for {@link Tuple}. + */ public static ZRangeByLexCommand stringsWithin(Range range) { + + Assert.notNull(range, "Range must not be null!"); + return new ZRangeByLexCommand(null, range, Direction.ASC, null); } + /** + * Creates a new {@link ZRangeByLexCommand} given a {@link Range} of {@link String} to obtain elements in reverse + * lexicographical ordering. + * + * @param range must not be {@literal null}. + * @return a new {@link ZRangeByLexCommand} for {@link Tuple}. + */ + public static ZRangeByLexCommand reverseStringsWithin(Range range) { + + Assert.notNull(range, "Range must not be null!"); + + return new ZRangeByLexCommand(null, range, Direction.DESC, null); + } + + /** + * Applies the {@literal key}. Constructs a new command instance with all previously configured properties. + * + * @param key must not be {@literal null}. + * @return a new {@link ZRangeByLexCommand} with {@literal key} applied. + */ public ZRangeByLexCommand from(ByteBuffer key) { + + Assert.notNull(key, "Key must not be null!"); + return new ZRangeByLexCommand(key, range, direction, limit); } + /** + * Applies the {@link Limit}. Constructs a new command instance with all previously configured properties. + * + * @param limit can be {@literal null}. + * @return a new {@link ZRangeByLexCommand} with {@link Limit} applied. + */ public ZRangeByLexCommand limitTo(Limit limit) { return new ZRangeByLexCommand(getKey(), range, direction, limit); } + /** + * @return + */ public Range getRange() { return range; } + /** + * @return + */ public Limit getLimit() { return limit; } + /** + * @return + */ public Direction getDirection() { return direction; } } /** - * Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. + * Get all elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -1134,7 +1654,7 @@ public interface ReactiveZSetCommands { } /** - * Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is + * Get all elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is * limited via {@link Limit}. * * @param key must not be {@literal null}. @@ -1144,15 +1664,15 @@ public interface ReactiveZSetCommands { */ default Mono> zRangeByLex(ByteBuffer key, Range range, Limit limit) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); return zRangeByLex(Mono.just(ZRangeByLexCommand.stringsWithin(range).from(key).limitTo(limit))).next() .map(MultiValueResponse::getOutput); } /** - * Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. + * Get all elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. * * @param key must not be {@literal null}. * @param range must not be {@literal null}. @@ -1163,7 +1683,7 @@ public interface ReactiveZSetCommands { } /** - * Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is + * Get all elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is * limited via {@link Limit}. * * @param key must not be {@literal null}. @@ -1173,22 +1693,19 @@ public interface ReactiveZSetCommands { */ default Mono> zRevRangeByLex(ByteBuffer key, Range range, Limit limit) { - Assert.notNull(key, "key must not be null"); - Assert.notNull(range, "range must not be null"); + Assert.notNull(key, "Key must not be null!"); + Assert.notNull(range, "Range must not be null!"); return zRangeByLex(Mono.just(ZRangeByLexCommand.reverseStringsWithin(range).from(key).limitTo(limit))).next() .map(MultiValueResponse::getOutput); } /** - * Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is + * Get all elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is * limited via {@link Limit} and sorted by {@link ZRangeByLexCommand#getDirection()}. * - * @param key must not be {@literal null}. - * @param range must not be {@literal null}. - * @param limit can be {@literal null}. + * @param commands must not be {@literal null}. * @return */ Flux> zRangeByLex(Publisher commands); - } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisClusterNode.java b/src/main/java/org/springframework/data/redis/connection/RedisClusterNode.java index 88c1aedbe..1d62ac6b1 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisClusterNode.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisClusterNode.java @@ -58,7 +58,7 @@ public class RedisClusterNode extends RedisNode { public RedisClusterNode(String id) { this(new SlotRange(Collections. emptySet())); - Assert.notNull(id, "Id must not be null"); + Assert.notNull(id, "Id must not be null!"); this.id = id; } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java index 60fd7b226..2d48653f6 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java @@ -1219,14 +1219,14 @@ public class LettuceConnection extends AbstractRedisConnection { } try { if (isPipelined()) { - pipeline(new LettuceStatusResult(((RedisAsyncCommands) getAsyncDedicatedConnection()).watch(keys))); + pipeline(new LettuceStatusResult(((RedisAsyncCommands) getAsyncDedicatedConnection()).watch((Object[]) keys))); return; } if (isQueueing()) { - transaction(new LettuceTxStatusResult(((RedisAsyncCommands) getDedicatedConnection()).watch())); + transaction(new LettuceTxStatusResult(((RedisAsyncCommands) getDedicatedConnection()).watch((Object[]) keys))); return; } - ((RedisCommands) getDedicatedConnection()).watch(keys); + ((RedisCommands) getDedicatedConnection()).watch((Object[]) keys); } catch (Exception ex) { throw convertLettuceAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java index df56ccb95..240d7943c 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java @@ -54,6 +54,7 @@ import org.springframework.data.redis.connection.convert.LongToBooleanConverter; import org.springframework.data.redis.connection.convert.StringToRedisClientInfoConverter; import org.springframework.data.redis.core.types.Expiration; import org.springframework.data.redis.core.types.RedisClientInfo; +import org.springframework.data.redis.util.ByteUtils; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; @@ -739,7 +740,7 @@ abstract public class LettuceConverters extends Converters { ByteBuffer buffer = ByteBuffer.allocate(prefix.length + value.length); buffer.put(prefix); buffer.put(value); - return toString(buffer.array()); + return toString(ByteUtils.getBytes(buffer)); } public static List partitionsToClusterNodes(Partitions partitions) { diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterGeoCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterGeoCommands.java index 43569dd01..97fe924b0 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterGeoCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterGeoCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import org.springframework.data.redis.connection.ReactiveClusterGeoCommands; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHashCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHashCommands.java index da1cff84f..5b7996da4 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHashCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHashCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import org.springframework.data.redis.connection.ReactiveClusterHashCommands; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHyperLogLogCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHyperLogLogCommands.java index fca3a3ab4..3cb19d220 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHyperLogLogCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterHyperLogLogCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import java.nio.ByteBuffer; @@ -24,7 +23,8 @@ import org.reactivestreams.Publisher; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.connection.ClusterSlotHashUtil; import org.springframework.data.redis.connection.ReactiveClusterHyperLogLogCommands; -import org.springframework.data.redis.connection.ReactiveRedisConnection; +import org.springframework.data.redis.connection.ReactiveRedisConnection.BooleanResponse; +import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; import org.springframework.util.Assert; import reactor.core.publisher.Flux; @@ -46,8 +46,11 @@ public class LettuceReactiveClusterHyperLogLogCommands extends LettuceReactiveHy super(connection); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveHyperLogLogCommands#pfMerge(org.reactivestreams.Publisher) + */ @Override - public Flux> pfMerge(Publisher commands) { + public Flux> pfMerge(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -66,9 +69,11 @@ public class LettuceReactiveClusterHyperLogLogCommands extends LettuceReactiveHy })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveHyperLogLogCommands#pfCount(org.reactivestreams.Publisher) + */ @Override - public Flux> pfCount( - Publisher commands) { + public Flux> pfCount(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterKeyCommands.java index 73f34375d..43d02dce3 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterKeyCommands.java @@ -23,7 +23,7 @@ import org.reactivestreams.Publisher; import org.springframework.data.redis.RedisSystemException; import org.springframework.data.redis.connection.ClusterSlotHashUtil; import org.springframework.data.redis.connection.ReactiveClusterKeyCommands; -import org.springframework.data.redis.connection.ReactiveRedisConnection; +import org.springframework.data.redis.connection.ReactiveRedisConnection.BooleanResponse; import org.springframework.data.redis.connection.RedisClusterNode; import org.springframework.util.Assert; @@ -51,6 +51,7 @@ public class LettuceReactiveClusterKeyCommands extends LettuceReactiveKeyCommand public LettuceReactiveClusterKeyCommands(LettuceReactiveRedisClusterConnection connection) { super(connection); + this.connection = connection; } @@ -76,12 +77,12 @@ public class LettuceReactiveClusterKeyCommands extends LettuceReactiveKeyCommand * @see org.springframework.data.redis.connection.ReactiveRedisConnection.ReactiveKeyCommands#rename(org.reactivestreams.Publisher, java.util.function.Supplier) */ @Override - public Flux> rename(Publisher commands) { + public Flux> rename(Publisher commands) { return connection.execute(cmd -> Flux.from(commands).flatMap(command -> { Assert.notNull(command.getKey(), "key must not be null."); - Assert.notNull(command.getNewName(), "NewName must not be null"); + Assert.notNull(command.getNewName(), "NewName must not be null!"); if (ClusterSlotHashUtil.isSameSlotForAllKeys(command.getKey(), command.getNewName())) { return super.rename(Mono.just(command)); @@ -93,7 +94,7 @@ public class LettuceReactiveClusterKeyCommands extends LettuceReactiveKeyCommand .flatMap(value -> cmd.restore(command.getNewName(), 0, value).flatMap(res -> cmd.del(command.getKey()))) .map(LettuceConverters.longToBooleanConverter()::convert); - return result.map(val -> new ReactiveRedisConnection.BooleanResponse<>(command, val)); + return result.map(val -> new BooleanResponse<>(command, val)); })); } @@ -102,12 +103,12 @@ public class LettuceReactiveClusterKeyCommands extends LettuceReactiveKeyCommand * @see org.springframework.data.redis.connection.ReactiveRedisConnection.ReactiveKeyCommands#renameNX(org.reactivestreams.Publisher, java.util.function.Supplier) */ @Override - public Flux> renameNX(Publisher commands) { + public Flux> renameNX(Publisher commands) { return connection.execute(cmd -> Flux.from(commands).flatMap(command -> { Assert.notNull(command.getKey(), "Key must not be null."); - Assert.notNull(command.getNewName(), "NewName must not be null"); + Assert.notNull(command.getNewName(), "NewName must not be null!"); if (ClusterSlotHashUtil.isSameSlotForAllKeys(command.getKey(), command.getNewName())) { return super.renameNX(Mono.just(command)); @@ -126,7 +127,7 @@ public class LettuceReactiveClusterKeyCommands extends LettuceReactiveKeyCommand .map(LettuceConverters.longToBooleanConverter()::convert); }); - return result.map(val -> new ReactiveRedisConnection.BooleanResponse<>(command, val)); + return result.map(val -> new BooleanResponse<>(command, val)); })); } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterListCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterListCommands.java index 22cb14927..2ce7601c6 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterListCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import java.nio.ByteBuffer; @@ -22,7 +21,7 @@ import org.reactivestreams.Publisher; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.connection.ClusterSlotHashUtil; import org.springframework.data.redis.connection.ReactiveClusterListCommands; -import org.springframework.data.redis.connection.ReactiveRedisConnection; +import org.springframework.data.redis.connection.ReactiveRedisConnection.ByteBufferResponse; import org.springframework.util.Assert; import reactor.core.publisher.Flux; @@ -45,6 +44,9 @@ public class LettuceReactiveClusterListCommands extends LettuceReactiveListComma super(connection); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveListCommands#bPop(org.reactivestreams.Publisher) + */ @Override public Flux bPop(Publisher commands) { @@ -61,9 +63,11 @@ public class LettuceReactiveClusterListCommands extends LettuceReactiveListComma })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveListCommands#rPopLPush(org.reactivestreams.Publisher) + */ @Override - public Flux> rPopLPush( - Publisher commands) { + public Flux> rPopLPush(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -77,7 +81,7 @@ public class LettuceReactiveClusterListCommands extends LettuceReactiveListComma Flux result = cmd.rpop(command.getKey()) .flatMap(value -> cmd.lpush(command.getDestination(), value).map(x -> value)); - return result.map(value -> new ReactiveRedisConnection.ByteBufferResponse<>(command, value)); + return result.map(value -> new ByteBufferResponse<>(command, value)); })); } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterNumberCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterNumberCommands.java index fce4dc24e..145f35d7a 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterNumberCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterNumberCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import org.springframework.data.redis.connection.ReactiveClusterNumberCommands; diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterSetCommands.java index 91686ce25..a9144fa74 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterSetCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import java.nio.ByteBuffer; @@ -24,7 +23,9 @@ import java.util.stream.Collectors; import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.ClusterSlotHashUtil; import org.springframework.data.redis.connection.ReactiveClusterSetCommands; -import org.springframework.data.redis.connection.ReactiveRedisConnection; +import org.springframework.data.redis.connection.ReactiveRedisConnection.BooleanResponse; +import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiValueResponse; +import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; import org.springframework.util.Assert; import reactor.core.publisher.Flux; @@ -47,9 +48,11 @@ public class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommand super(connection); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sUnion(org.reactivestreams.Publisher) + */ @Override - public Flux> sUnion( - Publisher commands) { + public Flux> sUnion(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -62,13 +65,15 @@ public class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommand Mono> result = Flux .merge(command.getKeys().stream().map(cmd::smembers).collect(Collectors.toList())).distinct().collectList(); - return result.map(value -> new ReactiveRedisConnection.MultiValueResponse<>(command, value)); + return result.map(value -> new MultiValueResponse<>(command, value)); })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sUnionStore(org.reactivestreams.Publisher) + */ @Override - public Flux> sUnionStore( - Publisher commands) { + public Flux> sUnionStore(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -84,14 +89,16 @@ public class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommand return sUnion(Mono.just(SUnionCommand.keys(command.getKeys()))).next().flatMap(values -> { Mono result = cmd.sadd(command.getKey(), values.getOutput().stream().toArray(ByteBuffer[]::new)); - return result.map(value -> new ReactiveRedisConnection.NumericResponse<>(command, value)); + return result.map(value -> new NumericResponse<>(command, value)); }); })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sInter(org.reactivestreams.Publisher) + */ @Override - public Flux> sInter( - Publisher commands) { + public Flux> sInter(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -115,13 +122,15 @@ public class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommand return source; }); - return result.map(value -> new ReactiveRedisConnection.MultiValueResponse<>(command, value)); + return result.map(value -> new MultiValueResponse<>(command, value)); })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sInterStore(org.reactivestreams.Publisher) + */ @Override - public Flux> sInterStore( - Publisher commands) { + public Flux> sInterStore(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -137,14 +146,16 @@ public class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommand return sInter(Mono.just(SInterCommand.keys(command.getKeys()))).next().flatMap(values -> { Mono result = cmd.sadd(command.getKey(), values.getOutput().stream().toArray(ByteBuffer[]::new)); - return result.map(value -> new ReactiveRedisConnection.NumericResponse<>(command, value)); + return result.map(value -> new NumericResponse<>(command, value)); }); })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sDiff(org.reactivestreams.Publisher) + */ @Override - public Flux> sDiff( - Publisher commands) { + public Flux> sDiff(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -168,14 +179,16 @@ public class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommand return source; }); - return result.map(value -> new ReactiveRedisConnection.MultiValueResponse<>(command, value)); + return result.map(value -> new MultiValueResponse<>(command, value)); })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sDiffStore(org.reactivestreams.Publisher) + */ @Override - public Flux> sDiffStore( - Publisher commands) { + public Flux> sDiffStore(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -191,13 +204,16 @@ public class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommand return sDiff(Mono.just(SDiffCommand.keys(command.getKeys()))).next().flatMap(values -> { Mono result = cmd.sadd(command.getKey(), values.getOutput().stream().toArray(ByteBuffer[]::new)); - return result.map(value -> new ReactiveRedisConnection.NumericResponse<>(command, value)); + return result.map(value -> new NumericResponse<>(command, value)); }); })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveSetCommands#sMove(org.reactivestreams.Publisher) + */ @Override - public Flux> sMove(Publisher commands) { + public Flux> sMove(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -227,8 +243,7 @@ public class LettuceReactiveClusterSetCommands extends LettuceReactiveSetCommand }); - return result.defaultIfEmpty(Boolean.FALSE) - .map(value -> new ReactiveRedisConnection.BooleanResponse<>(command, value)); + return result.defaultIfEmpty(Boolean.FALSE).map(value -> new BooleanResponse<>(command, value)); })); } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterStringCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterStringCommands.java index ba66d2990..54abc250f 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterStringCommands.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import java.nio.ByteBuffer; @@ -45,6 +44,9 @@ public class LettuceReactiveClusterStringCommands extends LettuceReactiveStringC super(connection); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveStringCommands#bitOp(org.reactivestreams.Publisher) + */ @Override public Flux> bitOp(Publisher commands) { @@ -62,6 +64,9 @@ public class LettuceReactiveClusterStringCommands extends LettuceReactiveStringC })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveStringCommands#mSetNX(org.reactivestreams.Publisher) + */ @Override public Flux> mSetNX(Publisher commands) { diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterZSetCommands.java index 2045f6e82..f14892bf5 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveClusterZSetCommands.java @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import org.reactivestreams.Publisher; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.connection.ClusterSlotHashUtil; import org.springframework.data.redis.connection.ReactiveClusterZSetCommands; -import org.springframework.data.redis.connection.ReactiveRedisConnection; +import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse; import org.springframework.util.Assert; import reactor.core.publisher.Flux; @@ -42,9 +41,11 @@ public class LettuceReactiveClusterZSetCommands extends LettuceReactiveZSetComma super(connection); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveZSetCommands#zUnionStore(org.reactivestreams.Publisher) + */ @Override - public Flux> zUnionStore( - Publisher commands) { + public Flux> zUnionStore(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { @@ -59,9 +60,11 @@ public class LettuceReactiveClusterZSetCommands extends LettuceReactiveZSetComma })); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveZSetCommands#zInterStore(org.reactivestreams.Publisher) + */ @Override - public Flux> zInterStore( - Publisher commands) { + public Flux> zInterStore(Publisher commands) { return getConnection().execute(cmd -> Flux.from(commands).flatMap(command -> { Assert.notEmpty(command.getSourceKeys(), "Source keys must not be null or empty."); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java index 4b6d6c1a8..1dcf53d1a 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveKeyCommands.java @@ -19,7 +19,6 @@ import java.nio.ByteBuffer; import java.util.List; import java.util.stream.Collectors; -import com.lambdaworks.redis.api.reactive.RedisKeyReactiveCommands; import org.reactivestreams.Publisher; import org.springframework.data.redis.connection.DataType; import org.springframework.data.redis.connection.ReactiveKeyCommands; @@ -33,6 +32,8 @@ import org.springframework.util.Assert; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import com.lambdaworks.redis.api.reactive.RedisKeyReactiveCommands; + /** * @author Christoph Strobl * @since 2.0 @@ -49,6 +50,7 @@ public class LettuceReactiveKeyCommands implements ReactiveKeyCommands { public LettuceReactiveKeyCommands(LettuceReactiveRedisConnection connection) { Assert.notNull(connection, "Connection must not be null!"); + this.connection = connection; } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java index 5f1a57eac..e73e27407 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveListCommands.java @@ -52,6 +52,7 @@ public class LettuceReactiveListCommands implements ReactiveListCommands { public LettuceReactiveListCommands(LettuceReactiveRedisConnection connection) { Assert.notNull(connection, "Connection must not be null!"); + this.connection = connection; } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveNumberCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveNumberCommands.java index 55ee8432f..f4d5c38d5 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveNumberCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveNumberCommands.java @@ -36,12 +36,13 @@ public class LettuceReactiveNumberCommands implements ReactiveNumberCommands { /** * Create new {@link LettuceReactiveStringCommands}. - * + * * @param connection must not be {@literal null}. */ public LettuceReactiveNumberCommands(LettuceReactiveRedisConnection connection) { Assert.notNull(connection, "Connection must not be null!"); + this.connection = connection; } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisClusterConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisClusterConnection.java index 6233d3107..61aa49c1c 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisClusterConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisClusterConnection.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.redis.connection.lettuce; import java.nio.ByteBuffer; @@ -42,46 +41,73 @@ public class LettuceReactiveRedisClusterConnection extends LettuceReactiveRedisC super(client); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#keyCommands() + */ @Override public LettuceReactiveClusterKeyCommands keyCommands() { return new LettuceReactiveClusterKeyCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#listCommands() + */ @Override public LettuceReactiveClusterListCommands listCommands() { return new LettuceReactiveClusterListCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#setCommands() + */ @Override public LettuceReactiveClusterSetCommands setCommands() { return new LettuceReactiveClusterSetCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#zSetCommands() + */ @Override public LettuceReactiveClusterZSetCommands zSetCommands() { return new LettuceReactiveClusterZSetCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#hyperLogLogCommands() + */ @Override public LettuceReactiveClusterHyperLogLogCommands hyperLogLogCommands() { return new LettuceReactiveClusterHyperLogLogCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#stringCommands() + */ @Override public LettuceReactiveClusterStringCommands stringCommands() { return new LettuceReactiveClusterStringCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#geoCommands() + */ @Override public LettuceReactiveClusterGeoCommands geoCommands() { return new LettuceReactiveClusterGeoCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#hashCommands() + */ @Override public LettuceReactiveClusterHashCommands hashCommands() { return new LettuceReactiveClusterHashCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#numberCommands() + */ @Override public LettuceReactiveClusterNumberCommands numberCommands() { return new LettuceReactiveClusterNumberCommands(this); @@ -103,6 +129,10 @@ public class LettuceReactiveRedisClusterConnection extends LettuceReactiveRedisC return Flux.defer(() -> callback.doWithCommands(getCommands(node))).onErrorResumeWith(translateExeception()); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#getConnection() + */ + @SuppressWarnings("unchecked") @Override protected StatefulRedisClusterConnection getConnection() { @@ -112,10 +142,14 @@ public class LettuceReactiveRedisClusterConnection extends LettuceReactiveRedisC return (StatefulRedisClusterConnection) super.getConnection(); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#getCommands() + */ protected RedisClusterReactiveCommands getCommands() { return getConnection().reactive(); } + @SuppressWarnings("unchecked") protected RedisReactiveCommands getCommands(RedisNode node) { if (!(getConnection() instanceof StatefulRedisClusterConnection)) { diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisConnection.java index 989bd6a41..62389d67b 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveRedisConnection.java @@ -19,7 +19,6 @@ import java.nio.ByteBuffer; import java.util.function.Function; import org.reactivestreams.Publisher; -import org.springframework.core.convert.converter.Converter; import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.data.redis.connection.*; @@ -35,8 +34,6 @@ import com.lambdaworks.redis.cluster.api.reactive.RedisClusterReactiveCommands; import com.lambdaworks.redis.codec.RedisCodec; import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import rx.Observable; /** * @author Christoph Strobl @@ -71,41 +68,65 @@ public class LettuceReactiveRedisConnection implements ReactiveRedisConnection { return new LettuceReactiveKeyCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection#stringCommands() + */ @Override public ReactiveStringCommands stringCommands() { return new LettuceReactiveStringCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection#numberCommands() + */ @Override public ReactiveNumberCommands numberCommands() { return new LettuceReactiveNumberCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection#listCommands() + */ @Override public ReactiveListCommands listCommands() { return new LettuceReactiveListCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection#setCommands() + */ @Override public ReactiveSetCommands setCommands() { return new LettuceReactiveSetCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection#zSetCommands() + */ @Override public ReactiveZSetCommands zSetCommands() { return new LettuceReactiveZSetCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection#hashCommands() + */ @Override public ReactiveHashCommands hashCommands() { return new LettuceReactiveHashCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection#geoCommands() + */ @Override public ReactiveGeoCommands geoCommands() { return new LettuceReactiveGeoCommands(this); } + /* (non-Javadoc) + * @see org.springframework.data.redis.connection.ReactiveRedisConnection#hyperLogLogCommands() + */ @Override public ReactiveHyperLogLogCommands hyperLogLogCommands() { return new LettuceReactiveHyperLogLogCommands(this); @@ -119,6 +140,9 @@ public class LettuceReactiveRedisConnection implements ReactiveRedisConnection { return Flux.defer(() -> callback.doWithCommands(getCommands())).onErrorResumeWith(translateExeception()); } + /* (non-Javadoc) + * @see java.io.Closeable#close() + */ @Override public void close() { connection.close(); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommands.java index 61f619001..6adcbeec3 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommands.java @@ -48,6 +48,7 @@ public class LettuceReactiveSetCommands implements ReactiveSetCommands { public LettuceReactiveSetCommands(LettuceReactiveRedisConnection connection) { Assert.notNull(connection, "Connection must not be null!"); + this.connection = connection; } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java index 3e1f374be..a8750a4e4 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStringCommands.java @@ -52,6 +52,7 @@ public class LettuceReactiveStringCommands implements ReactiveStringCommands { public LettuceReactiveStringCommands(LettuceReactiveRedisConnection connection) { Assert.notNull(connection, "Connection must not be null!"); + this.connection = connection; } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java index 6a5848bde..d880637d7 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java @@ -28,6 +28,7 @@ import org.springframework.data.redis.connection.ReactiveRedisConnection.Numeric import org.springframework.data.redis.connection.ReactiveZSetCommands; import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate; import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; +import org.springframework.data.redis.util.ByteUtils; import org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -61,6 +62,7 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { public LettuceReactiveZSetCommands(LettuceReactiveRedisConnection connection) { Assert.notNull(connection, "Connection must not be null!"); + this.connection = connection; } @@ -75,17 +77,16 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { return connection.execute(cmd -> Flux.from(commands).flatMap(command -> { Assert.notNull(command.getKey(), "Key must not be null!"); - Assert.notEmpty(command.getTuples(), "Tuples must not be empty or null."); + Assert.notEmpty(command.getTuples(), "Tuples must not be empty or null!"); ZAddArgs args = null; - if (command.getIncr().isPresent() || command.getUpsert().isPresent() - || command.getReturnTotalChanged().isPresent()) { + if (command.isIncr() || command.isUpsert() || command.isReturnTotalChanged()) { - if (command.getIncr().isPresent() && ObjectUtils.nullSafeEquals(command.getIncr().get(), Boolean.TRUE)) { + if (command.isIncr()) { if (command.getTuples().size() > 1) { - throw new IllegalArgumentException("ZADD INCR must not contain more than one tuple."); + throw new IllegalArgumentException("ZADD INCR must not contain more than one tuple!"); } Tuple tuple = command.getTuples().iterator().next(); @@ -94,18 +95,14 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { .map(value -> new NumericResponse<>(command, value)); } - if (command.getReturnTotalChanged().isPresent() - && ObjectUtils.nullSafeEquals(command.getReturnTotalChanged().get(), Boolean.TRUE)) { + if (command.isReturnTotalChanged()) { args = ZAddArgs.Builder.ch(); } - if (command.getUpsert().isPresent()) { - - if (command.getUpsert().get().equals(Boolean.TRUE)) { - args = ZAddArgs.Builder.nx(); - } else { - args = ZAddArgs.Builder.xx(); - } + if (command.isUpsert()) { + args = ZAddArgs.Builder.nx(); + } else { + args = ZAddArgs.Builder.xx(); } } @@ -188,8 +185,7 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { Mono> result; if (ObjectUtils.nullSafeEquals(command.getDirection(), Direction.ASC)) { - if (command.getWithScores().isPresent() - && ObjectUtils.nullSafeEquals(command.getWithScores().get(), Boolean.TRUE)) { + if (command.isWithScores()) { result = cmd .zrangeWithScores(command.getKey(), command.getRange().getLowerBound(), @@ -198,11 +194,10 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { } else { result = cmd.zrange(command.getKey(), command.getRange().getLowerBound(), command.getRange().getUpperBound()) - .map(value -> (Tuple) new DefaultTuple(getBytes(value), Double.NaN)).collectList(); + .map(value -> (Tuple) new DefaultTuple(ByteUtils.getBytes(value), Double.NaN)).collectList(); } } else { - if (command.getWithScores().isPresent() - && ObjectUtils.nullSafeEquals(command.getWithScores().get(), Boolean.TRUE)) { + if (command.isWithScores()) { result = cmd .zrevrangeWithScores(command.getKey(), command.getRange().getLowerBound(), @@ -212,7 +207,7 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { result = cmd .zrevrange(command.getKey(), command.getRange().getLowerBound(), command.getRange().getUpperBound()) - .map(value -> (Tuple) new DefaultTuple(getBytes(value), Double.NaN)).collectList(); + .map(value -> (Tuple) new DefaultTuple(ByteUtils.getBytes(value), Double.NaN)).collectList(); } } @@ -237,60 +232,55 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { Mono> result; if (ObjectUtils.nullSafeEquals(command.getDirection(), Direction.ASC)) { - + Range range = ArgumentConverters.toRange(command.getRange()); - - if (command.getWithScores().isPresent() - && ObjectUtils.nullSafeEquals(command.getWithScores().get(), Boolean.TRUE)) { + + if (command.isWithScores()) { if (!isLimited) { result = cmd.zrangebyscoreWithScores(command.getKey(), range) - .map(sc -> (Tuple) new DefaultTuple(getBytes(sc.getValue()), sc.getScore())).collectList(); + .map(sc -> (Tuple) new DefaultTuple(ByteUtils.getBytes(sc.getValue()), sc.getScore())).collectList(); } else { result = cmd - .zrangebyscoreWithScores(command.getKey(), range, - LettuceConverters.toLimit(command.getLimit().get())) - .map(sc -> (Tuple) new DefaultTuple(getBytes(sc.getValue()), sc.getScore())).collectList(); + .zrangebyscoreWithScores(command.getKey(), range, LettuceConverters.toLimit(command.getLimit().get())) + .map(sc -> (Tuple) new DefaultTuple(ByteUtils.getBytes(sc.getValue()), sc.getScore())).collectList(); } } else { if (!isLimited) { result = cmd.zrangebyscore(command.getKey(), range) - .map(value -> (Tuple) new DefaultTuple(getBytes(value), Double.NaN)).collectList(); + .map(value -> (Tuple) new DefaultTuple(ByteUtils.getBytes(value), Double.NaN)).collectList(); } else { - result = cmd - .zrangebyscore(command.getKey(), range, LettuceConverters.toLimit(command.getLimit().get())) - .map(value -> (Tuple) new DefaultTuple(getBytes(value), Double.NaN)).collectList(); + result = cmd.zrangebyscore(command.getKey(), range, LettuceConverters.toLimit(command.getLimit().get())) + .map(value -> (Tuple) new DefaultTuple(ByteUtils.getBytes(value), Double.NaN)).collectList(); } } } else { - + Range range = ArgumentConverters.toRevRange(command.getRange()); - - if (command.getWithScores().isPresent() - && ObjectUtils.nullSafeEquals(command.getWithScores().get(), Boolean.TRUE)) { + + if (command.isWithScores()) { if (!isLimited) { result = cmd.zrevrangebyscoreWithScores(command.getKey(), range) - .map(sc -> (Tuple) new DefaultTuple(getBytes(sc.getValue()), sc.getScore())).collectList(); + .map(sc -> (Tuple) new DefaultTuple(ByteUtils.getBytes(sc.getValue()), sc.getScore())).collectList(); } else { result = cmd .zrevrangebyscoreWithScores(command.getKey(), range, LettuceConverters.toLimit(command.getLimit().get())) - .map(sc -> (Tuple) new DefaultTuple(getBytes(sc.getValue()), sc.getScore())).collectList(); + .map(sc -> (Tuple) new DefaultTuple(ByteUtils.getBytes(sc.getValue()), sc.getScore())).collectList(); } } else { if (!isLimited) { result = cmd.zrevrangebyscore(command.getKey(), range) - .map(value -> (Tuple) new DefaultTuple(getBytes(value), Double.NaN)).collectList(); + .map(value -> (Tuple) new DefaultTuple(ByteUtils.getBytes(value), Double.NaN)).collectList(); } else { - result = cmd - .zrevrangebyscore(command.getKey(), range, LettuceConverters.toLimit(command.getLimit().get())) - .map(value -> (Tuple) new DefaultTuple(getBytes(value), Double.NaN)).collectList(); + result = cmd.zrevrangebyscore(command.getKey(), range, LettuceConverters.toLimit(command.getLimit().get())) + .map(value -> (Tuple) new DefaultTuple(ByteUtils.getBytes(value), Double.NaN)).collectList(); } } } @@ -451,13 +441,14 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { Flux result; - if (command.getLimit() != null) { if (ObjectUtils.nullSafeEquals(command.getDirection(), Direction.ASC)) { - result = cmd.zrangebylex(command.getKey(), ArgumentConverters.toRange(command.getRange()), LettuceConverters.toLimit(command.getLimit())); + result = cmd.zrangebylex(command.getKey(), ArgumentConverters.toRange(command.getRange()), + LettuceConverters.toLimit(command.getLimit())); } else { - result = cmd.zrevrangebylex(command.getKey(), ArgumentConverters.toRevRange(command.getRange()), LettuceConverters.toLimit(command.getLimit())); + result = cmd.zrevrangebylex(command.getKey(), ArgumentConverters.toRevRange(command.getRange()), + LettuceConverters.toLimit(command.getLimit())); } } else { if (ObjectUtils.nullSafeEquals(command.getDirection(), Direction.ASC)) { @@ -499,14 +490,7 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { } private static byte[] getBytes(ScoredValue scoredValue) { - return scoredValue.optional().map(LettuceReactiveZSetCommands::getBytes).orElse(new byte[0]); - } - - private static byte[] getBytes(ByteBuffer byteBuffer) { - - byte[] bytes = new byte[byteBuffer.remaining()]; - byteBuffer.get(bytes); - return bytes; + return scoredValue.optional().map(ByteUtils::getBytes).orElse(new byte[0]); } protected LettuceReactiveRedisConnection getConnection() { @@ -517,23 +501,23 @@ public class LettuceReactiveZSetCommands implements ReactiveZSetCommands { * @author Christoph Strobl * @author Mark Paluch */ - static class ArgumentConverters { + private static class ArgumentConverters { - public static Range toRange(org.springframework.data.domain.Range range) { + static Range toRange(org.springframework.data.domain.Range range) { return Range.from(lowerBoundArgOf(range), upperBoundArgOf(range)); } - - public static Range toRevRange(org.springframework.data.domain.Range range) { + + static Range toRevRange(org.springframework.data.domain.Range range) { return Range.from(upperBoundArgOf(range), lowerBoundArgOf(range)); } @SuppressWarnings("unchecked") - public static Boundary lowerBoundArgOf(org.springframework.data.domain.Range range) { + static Boundary lowerBoundArgOf(org.springframework.data.domain.Range range) { return (Boundary) rangeToBoundArgumentConverter(false).convert(range); } @SuppressWarnings("unchecked") - public static Boundary upperBoundArgOf(org.springframework.data.domain.Range range) { + static Boundary upperBoundArgOf(org.springframework.data.domain.Range range) { return (Boundary) rangeToBoundArgumentConverter(true).convert(range); } diff --git a/src/main/java/org/springframework/data/redis/util/ByteUtils.java b/src/main/java/org/springframework/data/redis/util/ByteUtils.java index 1c9235dc2..f7ef523d9 100644 --- a/src/main/java/org/springframework/data/redis/util/ByteUtils.java +++ b/src/main/java/org/springframework/data/redis/util/ByteUtils.java @@ -15,6 +15,7 @@ */ package org.springframework.data.redis.util; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -98,4 +99,21 @@ public final class ByteUtils { return result; } + + /** + * Extract a byte array from {@link ByteBuffer} without consuming it. + * + * @param byteBuffer must not be {@literal null}. + * @return + * @since 2.0 + */ + public static byte[] getBytes(ByteBuffer byteBuffer) { + + Assert.notNull(byteBuffer, "ByteBuffer must not be null!"); + + ByteBuffer duplicate = byteBuffer.duplicate(); + byte[] bytes = new byte[duplicate.remaining()]; + duplicate.get(bytes); + return bytes; + } } diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHashCommandsTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHashCommandsTests.java index c683f99ad..8040c9b07 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHashCommandsTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveHashCommandsTests.java @@ -25,6 +25,7 @@ import static org.junit.Assert.*; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.Arrays; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -32,6 +33,7 @@ import org.junit.Test; /** * @author Christoph Strobl + * @author Mark Paluch */ public class LettuceReactiveHashCommandsTests extends LettuceReactiveCommandsTestsBase { @@ -232,13 +234,17 @@ public class LettuceReactiveHashCommandsTests extends LettuceReactiveCommandsTes * @see DATAREDIS-525 */ @Test - public void hGetAlllShouldReturnEntriesCorrectly() { + public void hGetAllShouldReturnEntriesCorrectly() { nativeCommands.hset(KEY_1, FIELD_1, VALUE_1); nativeCommands.hset(KEY_1, FIELD_2, VALUE_2); nativeCommands.hset(KEY_1, FIELD_3, VALUE_3); - System.out.println(connection.hashCommands().hGetAll(KEY_1_BBUFFER).block()); - } + Map expected = new HashMap<>(); + expected.put(FIELD_1_BBUFFER, VALUE_1_BBUFFER); + expected.put(FIELD_2_BBUFFER, VALUE_2_BBUFFER); + expected.put(FIELD_3_BBUFFER, VALUE_3_BBUFFER); + assertThat(connection.hashCommands().hGetAll(KEY_1_BBUFFER).block(), is(equalTo(expected))); + } } diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommandsTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommandsTests.java index 3a1fb367f..a3827de59 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommandsTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveSetCommandsTests.java @@ -116,7 +116,7 @@ public class LettuceReactiveSetCommandsTests extends LettuceReactiveCommandsTest nativeCommands.sadd(KEY_1, VALUE_1, VALUE_2); nativeCommands.sadd(KEY_2, VALUE_1); - assertThat(connection.setCommands().sMove(KEY_1_BBUFFER, KEY_2_BBUFFER, VALUE_3_BBUFFER).block(), is(false)); + assertThat(connection.setCommands().sMove(KEY_1_BBUFFER, KEY_2_BBUFFER, VALUE_3_BBUFFER).block(), is(false)); assertThat(nativeCommands.sismember(KEY_2, VALUE_3), is(false)); }