Add support for ZPOPMIN, ZPOPMAX and their blocking variants.

We now support ZPOPMIN, BZPOPMIN, ZPOPMAX and BZPOPMAX through the Template API for all drivers.

Closes #2007
Original Pull Request: #2088
This commit is contained in:
Mark Paluch
2021-06-16 13:49:15 +02:00
committed by Christoph Strobl
parent d13f9da212
commit 0f2039d5a0
28 changed files with 1856 additions and 21 deletions

View File

@@ -1830,6 +1830,52 @@ public abstract class AbstractConnectionIntegrationTests {
assertThat((Long) results.get(11)).isEqualTo(3);
}
@Test // GH-2007
@EnabledOnCommand("ZPOPMIN")
void zPopMin() {
actual.add(connection.zAdd("myzset", 1, "a"));
actual.add(connection.zAdd("myzset", 2, "b"));
actual.add(connection.zAdd("myzset", 3, "c"));
actual.add(connection.zAdd("myzset", 4, "d"));
actual.add(connection.zPopMin("myzset"));
actual.add(connection.bZPopMin("myzset", 1, TimeUnit.SECONDS));
actual.add(connection.zPopMin("myzset", 2));
actual.add(connection.zPopMin("myzset"));
List<Object> results = getResults();
assertThat(results.get(4)).isEqualTo(new DefaultStringTuple("a".getBytes(), "a", 1D));
assertThat(results.get(5)).isEqualTo(new DefaultStringTuple("b".getBytes(), "b", 2D));
assertThat((Collection) results.get(6)).containsExactly(new DefaultStringTuple("c".getBytes(), "c", 3D),
new DefaultStringTuple("d".getBytes(), "d", 4D));
assertThat(results.get(7)).isNull();
}
@Test // GH-2007
@EnabledOnCommand("ZPOPMAX")
void zPopMax() {
actual.add(connection.zAdd("myzset", 1, "a"));
actual.add(connection.zAdd("myzset", 2, "b"));
actual.add(connection.zAdd("myzset", 3, "c"));
actual.add(connection.zAdd("myzset", 4, "d"));
actual.add(connection.zPopMax("myzset"));
actual.add(connection.bZPopMax("myzset", 1, TimeUnit.SECONDS));
actual.add(connection.zPopMax("myzset", 2));
actual.add(connection.zPopMax("myzset"));
List<Object> results = getResults();
assertThat(results.get(4)).isEqualTo(new DefaultStringTuple("d".getBytes(), "d", 4D));
assertThat(results.get(5)).isEqualTo(new DefaultStringTuple("c".getBytes(), "c", 3D));
assertThat((Collection) results.get(6)).containsExactly(new DefaultStringTuple("b".getBytes(), "b", 2D),
new DefaultStringTuple("a".getBytes(), "a", 1D));
assertThat(results.get(7)).isNull();
}
@Test
void testZIncrBy() {
actual.add(connection.zAdd("myset", 2, "Bob"));

View File

@@ -610,6 +610,18 @@ public interface ClusterConnectionTests {
// DATAREDIS-315
void zInterStoreShouldWorkForSameSlotKeys();
// GH-2007
void zPopMinShouldWorkCorrectly();
// GH-2007
void bzPopMinShouldWorkCorrectly();
// GH-2007
void zPopMaxShouldWorkCorrectly();
// GH-2007
void bzPopMaxShouldWorkCorrectly();
// DATAREDIS-315
void zRangeByLexShouldReturnResultCorrectly();

View File

@@ -2026,6 +2026,56 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(nativeConnection.zrange(SAME_SLOT_KEY_3_BYTES, 0, -1)).contains(VALUE_2_BYTES);
}
@Test // GH-2007
@EnabledOnCommand("ZPOPMIN")
public void zPopMinShouldWorkCorrectly() {
nativeConnection.zadd(KEY_1_BYTES, 10D, VALUE_1_BYTES);
nativeConnection.zadd(KEY_1_BYTES, 20D, VALUE_2_BYTES);
nativeConnection.zadd(KEY_1_BYTES, 30D, VALUE_3_BYTES);
assertThat(clusterConnection.zPopMin(KEY_1_BYTES)).isEqualTo(new DefaultTuple(VALUE_1_BYTES, 10D));
assertThat(clusterConnection.zPopMin(KEY_1_BYTES, 2)).containsExactly(new DefaultTuple(VALUE_2_BYTES, 20D),
new DefaultTuple(VALUE_3_BYTES, 30D));
}
@Test // GH-2007
@EnabledOnCommand("BZPOPMIN")
public void bzPopMinShouldWorkCorrectly() {
nativeConnection.zadd(KEY_1_BYTES, 10D, VALUE_1_BYTES);
nativeConnection.zadd(KEY_1_BYTES, 20D, VALUE_2_BYTES);
nativeConnection.zadd(KEY_1_BYTES, 30D, VALUE_3_BYTES);
assertThat(clusterConnection.bZPopMin(KEY_1_BYTES, 1, TimeUnit.SECONDS))
.isEqualTo(new DefaultTuple(VALUE_1_BYTES, 10D));
}
@Test // GH-2007
@EnabledOnCommand("ZPOPMAX")
public void zPopMaxShouldWorkCorrectly() {
nativeConnection.zadd(KEY_1_BYTES, 10D, VALUE_1_BYTES);
nativeConnection.zadd(KEY_1_BYTES, 20D, VALUE_2_BYTES);
nativeConnection.zadd(KEY_1_BYTES, 30D, VALUE_3_BYTES);
assertThat(clusterConnection.zPopMax(KEY_1_BYTES)).isEqualTo(new DefaultTuple(VALUE_3_BYTES, 30D));
assertThat(clusterConnection.zPopMax(KEY_1_BYTES, 2)).containsExactly(new DefaultTuple(VALUE_2_BYTES, 20D),
new DefaultTuple(VALUE_1_BYTES, 10D));
}
@Test // GH-2007
@EnabledOnCommand("BZPOPMAX")
public void bzPopMaxShouldWorkCorrectly() {
nativeConnection.zadd(KEY_1_BYTES, 10D, VALUE_1_BYTES);
nativeConnection.zadd(KEY_1_BYTES, 20D, VALUE_2_BYTES);
nativeConnection.zadd(KEY_1_BYTES, 30D, VALUE_3_BYTES);
assertThat(clusterConnection.bZPopMax(KEY_1_BYTES, 1, TimeUnit.SECONDS))
.isEqualTo(new DefaultTuple(VALUE_3_BYTES, 30D));
}
@Test // DATAREDIS-315
public void zRangeByLexShouldReturnResultCorrectly() {

View File

@@ -2067,6 +2067,56 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(nativeConnection.zrange(SAME_SLOT_KEY_3, 0, -1)).contains(VALUE_2);
}
@Test // GH-2007
@EnabledOnCommand("ZPOPMIN")
public void zPopMinShouldWorkCorrectly() {
nativeConnection.zadd(KEY_1, 10D, VALUE_1);
nativeConnection.zadd(KEY_1, 20D, VALUE_2);
nativeConnection.zadd(KEY_1, 30D, VALUE_3);
assertThat(clusterConnection.zPopMin(KEY_1_BYTES)).isEqualTo(new DefaultTuple(VALUE_1_BYTES, 10D));
assertThat(clusterConnection.zPopMin(KEY_1_BYTES, 2)).containsExactly(new DefaultTuple(VALUE_2_BYTES, 20D),
new DefaultTuple(VALUE_3_BYTES, 30D));
}
@Test // GH-2007
@EnabledOnCommand("BZPOPMIN")
public void bzPopMinShouldWorkCorrectly() {
nativeConnection.zadd(KEY_1, 10D, VALUE_1);
nativeConnection.zadd(KEY_1, 20D, VALUE_2);
nativeConnection.zadd(KEY_1, 30D, VALUE_3);
assertThat(clusterConnection.bZPopMin(KEY_1_BYTES, 1, TimeUnit.SECONDS))
.isEqualTo(new DefaultTuple(VALUE_1_BYTES, 10D));
}
@Test // GH-2007
@EnabledOnCommand("ZPOPMAX")
public void zPopMaxShouldWorkCorrectly() {
nativeConnection.zadd(KEY_1, 10D, VALUE_1);
nativeConnection.zadd(KEY_1, 20D, VALUE_2);
nativeConnection.zadd(KEY_1, 30D, VALUE_3);
assertThat(clusterConnection.zPopMax(KEY_1_BYTES)).isEqualTo(new DefaultTuple(VALUE_3_BYTES, 30D));
assertThat(clusterConnection.zPopMax(KEY_1_BYTES, 2)).containsExactly(new DefaultTuple(VALUE_2_BYTES, 20D),
new DefaultTuple(VALUE_1_BYTES, 10D));
}
@Test // GH-2007
@EnabledOnCommand("BZPOPMAX")
public void bzPopMaxShouldWorkCorrectly() {
nativeConnection.zadd(KEY_1, 10D, VALUE_1);
nativeConnection.zadd(KEY_1, 20D, VALUE_2);
nativeConnection.zadd(KEY_1, 30D, VALUE_3);
assertThat(clusterConnection.bZPopMax(KEY_1_BYTES, 1, TimeUnit.SECONDS))
.isEqualTo(new DefaultTuple(VALUE_3_BYTES, 30D));
}
@Test // DATAREDIS-315
public void zRangeByLexShouldReturnResultCorrectly() {

View File

@@ -22,6 +22,7 @@ import static org.springframework.data.domain.Range.Bound.*;
import reactor.test.StepVerifier;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.Arrays;
import org.springframework.data.domain.Range;
@@ -385,6 +386,62 @@ public class LettuceReactiveZSetCommandsIntegrationTests extends LettuceReactive
.isEqualTo(2L);
}
@ParameterizedRedisTest // GH-2007
@EnabledOnCommand("ZPOPMIN")
void zPopMinShouldReturnCorrectly() {
nativeCommands.zadd(KEY_1, 1D, VALUE_1);
nativeCommands.zadd(KEY_1, 2D, VALUE_2);
nativeCommands.zadd(KEY_1, 3D, VALUE_3);
connection.zSetCommands().zPopMin(KEY_1_BBUFFER).as(StepVerifier::create)
.expectNext(new DefaultTuple(VALUE_1_BYTES, 1D)).verifyComplete();
connection.zSetCommands().zPopMin(KEY_1_BBUFFER, 2).as(StepVerifier::create)
.expectNext(new DefaultTuple(VALUE_2_BYTES, 2D)).expectNext(new DefaultTuple(VALUE_3_BYTES, 3D))
.verifyComplete();
}
@ParameterizedRedisTest // GH-2007
@EnabledOnCommand("BZPOPMIN")
void bzPopMinShouldReturnCorrectly() {
nativeCommands.zadd(KEY_1, 1D, VALUE_1);
nativeCommands.zadd(KEY_1, 2D, VALUE_2);
nativeCommands.zadd(KEY_1, 3D, VALUE_3);
connection.zSetCommands().bZPopMin(KEY_1_BBUFFER, Duration.ofSeconds(1)).as(StepVerifier::create)
.expectNext(new DefaultTuple(VALUE_1_BYTES, 1D)).verifyComplete();
}
@ParameterizedRedisTest // GH-2007
@EnabledOnCommand("ZPOPMAX")
void zPopMaxShouldReturnCorrectly() {
nativeCommands.zadd(KEY_1, 1D, VALUE_1);
nativeCommands.zadd(KEY_1, 2D, VALUE_2);
nativeCommands.zadd(KEY_1, 3D, VALUE_3);
connection.zSetCommands().zPopMax(KEY_1_BBUFFER).as(StepVerifier::create)
.expectNext(new DefaultTuple(VALUE_3_BYTES, 3D)).verifyComplete();
connection.zSetCommands().zPopMax(KEY_1_BBUFFER, 2).as(StepVerifier::create)
.expectNext(new DefaultTuple(VALUE_2_BYTES, 2D)).expectNext(new DefaultTuple(VALUE_1_BYTES, 1D))
.verifyComplete();
}
@ParameterizedRedisTest // GH-2007
@EnabledOnCommand("BZPOPMAX")
void bzPopMaxShouldReturnCorrectly() {
nativeCommands.zadd(KEY_1, 1D, VALUE_1);
nativeCommands.zadd(KEY_1, 2D, VALUE_2);
nativeCommands.zadd(KEY_1, 3D, VALUE_3);
connection.zSetCommands().bZPopMax(KEY_1_BBUFFER, Duration.ofSeconds(1)).as(StepVerifier::create)
.expectNext(new DefaultTuple(VALUE_3_BYTES, 3D)).verifyComplete();
}
@ParameterizedRedisTest // DATAREDIS-525
void zCardShouldReturnSizeCorrectly() {

View File

@@ -20,6 +20,7 @@ import static org.assertj.core.api.Assumptions.*;
import reactor.test.StepVerifier;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -434,6 +435,52 @@ public class DefaultReactiveZSetOperationsIntegrationTests<K, V> {
zSetOperations.lexCount(key, Range.rightOpen("b", "f")).as(StepVerifier::create).expectNext(4L).verifyComplete();
}
@ParameterizedRedisTest // GH-2007
@EnabledOnCommand("ZPOPMIN")
void popMin() {
K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();
V value3 = valueFactory.instance();
V value4 = valueFactory.instance();
zSetOperations.add(key, value1, 1).as(StepVerifier::create).expectNext(true).verifyComplete();
zSetOperations.add(key, value2, 2).as(StepVerifier::create).expectNext(true).verifyComplete();
zSetOperations.add(key, value3, 3).as(StepVerifier::create).expectNext(true).verifyComplete();
zSetOperations.add(key, value4, 4).as(StepVerifier::create).expectNext(true).verifyComplete();
zSetOperations.popMin(key).as(StepVerifier::create).expectNext(new DefaultTypedTuple<>(value1, 1D))
.verifyComplete();
zSetOperations.popMin(key, Duration.ofSeconds(1)).as(StepVerifier::create)
.expectNext(new DefaultTypedTuple<>(value2, 2D)).verifyComplete();
zSetOperations.popMin(key, 2).as(StepVerifier::create).expectNext(new DefaultTypedTuple<>(value3, 3D))
.expectNext(new DefaultTypedTuple<>(value4, 4D)).verifyComplete();
}
@ParameterizedRedisTest // GH-2007
@EnabledOnCommand("ZPOPMAX")
void popMax() {
K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();
V value3 = valueFactory.instance();
V value4 = valueFactory.instance();
zSetOperations.add(key, value1, 1).as(StepVerifier::create).expectNext(true).verifyComplete();
zSetOperations.add(key, value2, 2).as(StepVerifier::create).expectNext(true).verifyComplete();
zSetOperations.add(key, value3, 3).as(StepVerifier::create).expectNext(true).verifyComplete();
zSetOperations.add(key, value4, 4).as(StepVerifier::create).expectNext(true).verifyComplete();
zSetOperations.popMax(key).as(StepVerifier::create).expectNext(new DefaultTypedTuple<>(value4, 4D))
.verifyComplete();
zSetOperations.popMax(key, Duration.ofSeconds(1)).as(StepVerifier::create)
.expectNext(new DefaultTypedTuple<>(value3, 3D)).verifyComplete();
zSetOperations.popMax(key, 2).as(StepVerifier::create).expectNext(new DefaultTypedTuple<>(value2, 2D))
.expectNext(new DefaultTypedTuple<>(value1, 1D)).verifyComplete();
}
@ParameterizedRedisTest // DATAREDIS-602
void size() {

View File

@@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeEach;
@@ -35,6 +36,7 @@ import org.springframework.data.redis.ObjectFactory;
import org.springframework.data.redis.connection.RedisZSetCommands;
import org.springframework.data.redis.connection.RedisZSetCommands.Weights;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.data.redis.test.condition.EnabledOnCommand;
import org.springframework.data.redis.test.extension.parametrized.MethodSource;
import org.springframework.data.redis.test.extension.parametrized.ParameterizedRedisTest;
@@ -128,6 +130,48 @@ public class DefaultZSetOperationsIntegrationTests<K, V> {
assertThat(zSetOps.lexCount(key, RedisZSetCommands.Range.range().gt(value1))).isEqualTo(2);
}
@ParameterizedRedisTest // GH-2007
@EnabledOnCommand("ZPOPMIN")
void testPopMin() {
K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();
V value3 = valueFactory.instance();
V value4 = valueFactory.instance();
zSetOps.add(key, value1, 1);
zSetOps.add(key, value2, 2);
zSetOps.add(key, value3, 3);
zSetOps.add(key, value4, 4);
assertThat(zSetOps.popMin(key)).isEqualTo(new DefaultTypedTuple<>(value1, 1d));
assertThat(zSetOps.popMin(key, 2)).containsExactly(new DefaultTypedTuple<>(value2, 2d),
new DefaultTypedTuple<>(value3, 3d));
assertThat(zSetOps.popMin(key, 1, TimeUnit.SECONDS)).isEqualTo(new DefaultTypedTuple<>(value4, 4d));
}
@ParameterizedRedisTest // GH-2007
@EnabledOnCommand("ZPOPMAX")
void testPopMax() {
K key = keyFactory.instance();
V value1 = valueFactory.instance();
V value2 = valueFactory.instance();
V value3 = valueFactory.instance();
V value4 = valueFactory.instance();
zSetOps.add(key, value1, 1);
zSetOps.add(key, value2, 2);
zSetOps.add(key, value3, 3);
zSetOps.add(key, value4, 4);
assertThat(zSetOps.popMax(key)).isEqualTo(new DefaultTypedTuple<>(value4, 4d));
assertThat(zSetOps.popMax(key, 2)).containsExactly(new DefaultTypedTuple<>(value3, 3d),
new DefaultTypedTuple<>(value2, 2d));
assertThat(zSetOps.popMax(key, 1, TimeUnit.SECONDS)).isEqualTo(new DefaultTypedTuple<>(value1, 1d));
}
@ParameterizedRedisTest
void testIncrementScore() {