Polishing.

Update javadoc and format sources.

See #3054.
This commit is contained in:
Christoph Strobl
2025-03-05 11:59:20 +01:00
committed by Mark Paluch
parent c6ba95f271
commit 06f35914c5
15 changed files with 431 additions and 293 deletions

View File

@@ -865,22 +865,52 @@ public interface ReactiveHashCommands {
this.options = options;
}
/**
* Creates a new {@link ExpireCommand}.
*
* @param fields the {@code field} names to apply expiration to
* @param timeout the actual timeout
* @param unit the unit of measure for the {@code timeout}.
* @return new instance of {@link ExpireCommand}.
*/
public static ExpireCommand expire(List<ByteBuffer> fields, long timeout, TimeUnit unit) {
Assert.notNull(fields, "Field must not be null");
return expire(fields, Expiration.from(timeout, unit));
}
/**
* Creates a new {@link ExpireCommand}.
*
* @param fields the {@code field} names to apply expiration to.
* @param ttl the actual timeout.
* @return new instance of {@link ExpireCommand}.
*/
public static ExpireCommand expire(List<ByteBuffer> fields, Duration ttl) {
Assert.notNull(fields, "Field must not be null");
return expire(fields, Expiration.from(ttl));
}
/**
* Creates a new {@link ExpireCommand}.
*
* @param fields the {@code field} names to apply expiration to
* @param expiration the {@link Expiration} to apply to the given {@literal fields}.
* @return new instance of {@link ExpireCommand}.
*/
public static ExpireCommand expire(List<ByteBuffer> fields, Expiration expiration) {
return new ExpireCommand(null, fields, expiration, FieldExpirationOptions.none());
}
/**
* Creates a new {@link ExpireCommand}.
*
* @param fields the {@code field} names to apply expiration to
* @param ttl the unix point in time when to expire the given {@literal fields}.
* @param precision can be {@link TimeUnit#SECONDS} or {@link TimeUnit#MILLISECONDS}.
* @return new instance of {@link ExpireCommand}.
*/
public static ExpireCommand expireAt(List<ByteBuffer> fields, Instant ttl, TimeUnit precision) {
if (precision.compareTo(TimeUnit.MILLISECONDS) > 0) {
@@ -890,10 +920,18 @@ public interface ReactiveHashCommands {
return expire(fields, Expiration.unixTimestamp(ttl.toEpochMilli(), TimeUnit.MILLISECONDS));
}
/**
* @param key the {@literal key} from which to expire the {@literal fields} from.
* @return new instance of {@link ExpireCommand}.
*/
public ExpireCommand from(ByteBuffer key) {
return new ExpireCommand(key, getFields(), expiration, options);
}
/**
* @param options additional options to be sent along with the command.
* @return new instance of {@link ExpireCommand}.
*/
public ExpireCommand withOptions(FieldExpirationOptions options) {
return new ExpireCommand(getKey(), getFields(), getExpiration(), options);
}

View File

@@ -255,11 +255,34 @@ public interface RedisHashCommands {
@Nullable
Long hStrLen(byte[] key, byte[] field);
/**
* Apply a given {@link org.springframework.data.redis.core.types.Expiration} to the given {@literal fields}.
*
* @param key must not be {@literal null}.
* @param expiration the {@link org.springframework.data.redis.core.types.Expiration} to apply.
* @param fields the names of the {@literal fields} to apply the {@literal expiration} to.
* @return a {@link List} holding the command result for each field in order - {@code 2} indicating the specific field
* is deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration
* time is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating there is no
* such field;
* @since 3.5
*/
default @Nullable List<Long> applyExpiration(byte[] key,
org.springframework.data.redis.core.types.Expiration expiration, byte[]... fields) {
return applyExpiration(key, expiration, FieldExpirationOptions.none(), fields);
}
/**
* @param key must not be {@literal null}.
* @param expiration the {@link org.springframework.data.redis.core.types.Expiration} to apply.
* @param options additional options to be sent along with the command.
* @param fields the names of the {@literal fields} to apply the {@literal expiration} to.
* @return a {@link List} holding the command result for each field in order - {@code 2} indicating the specific field
* is deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration
* time is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX | GT | LT
* condition is not met); {@code -2} indicating there is no such field;
* @since 3.5
*/
@Nullable
default List<Long> applyExpiration(byte[] key, org.springframework.data.redis.core.types.Expiration expiration,
FieldExpirationOptions options, byte[]... fields) {
@@ -304,9 +327,8 @@ public interface RedisHashCommands {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration time
* is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX | GT | LT condition
* is not met); {@code -2} indicating there is no such field; {@literal null} when used in pipeline /
* transaction.
* is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating there is no such
* field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hexpire/">Redis Documentation: HEXPIRE</a>
* @since 3.5
*/
@@ -324,9 +346,8 @@ public interface RedisHashCommands {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration time
* is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX | GT | LT condition
* is not met); {@code -2} indicating there is no such field; {@literal null} when used in pipeline /
* transaction.
* is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating there is no such
* field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hexpire/">Redis Documentation: HEXPIRE</a>
* @since 3.5
*/
@@ -362,9 +383,8 @@ public interface RedisHashCommands {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration time
* is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX | GT | LT condition
* is not met); {@code -2} indicating there is no such field; {@literal null} when used in pipeline /
* transaction.
* is set/updated; {@code 0} indicating the expiration time is not set ; {@code -2} indicating there is no
* such field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hpexpire/">Redis Documentation: HPEXPIRE</a>
* @since 3.5
*/
@@ -382,9 +402,8 @@ public interface RedisHashCommands {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration time
* is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX | GT | LT condition
* is not met); {@code -2} indicating there is no such field; {@literal null} when used in pipeline /
* transaction.
* is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating there is no such
* field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hpexpire/">Redis Documentation: HPEXPIRE</a>
* @since 3.5
*/
@@ -420,9 +439,8 @@ public interface RedisHashCommands {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is in the past; {@code 1} indicating
* expiration time is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX |
* GT | LT condition is not met); {@code -2} indicating there is no such field; {@literal null} when used in
* pipeline / transaction.
* expiration time is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating
* there is no such field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hexpireat/">Redis Documentation: HEXPIREAT</a>
* @since 3.5
*/
@@ -457,9 +475,8 @@ public interface RedisHashCommands {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is in the past; {@code 1} indicating
* expiration time is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX |
* GT | LT condition is not met); {@code -2} indicating there is no such field; {@literal null} when used in
* pipeline / transaction.
* expiration time is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating
* there is no such field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hpexpireat/">Redis Documentation: HPEXPIREAT</a>
* @since 3.5
*/
@@ -531,8 +548,6 @@ public interface RedisHashCommands {
* @since 3.5
*/
@Nullable
// TODO: this is complete nonsense as it would jeopardize negative values
// TODO: this should be a List<Map.Entry<byte, Expiration>>
List<Long> hTtl(byte[] key, TimeUnit timeUnit, byte[]... fields);
/**

View File

@@ -2341,9 +2341,8 @@ public interface StringRedisConnection extends RedisConnection {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration time
* is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX | GT | LT condition
* is not met); {@code -2} indicating there is no such field; {@literal null} when used in pipeline /
* transaction.
* is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating there is no such
* field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hexpire/">Redis Documentation: HEXPIRE</a>
* @since 3.5
*/
@@ -2377,9 +2376,8 @@ public interface StringRedisConnection extends RedisConnection {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration time
* is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX | GT | LT condition
* is not met); {@code -2} indicating there is no such field; {@literal null} when used in pipeline /
* transaction.
* is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating there is no such
* field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hpexpire/">Redis Documentation: HPEXPIRE</a>
* @since 3.5
*/
@@ -2413,9 +2411,8 @@ public interface StringRedisConnection extends RedisConnection {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is in the past; {@code 1} indicating
* expiration time is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX |
* GT | LT condition is not met); {@code -2} indicating there is no such field; {@literal null} when used in
* pipeline / transaction.
* expiration time is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating
* there is no such field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hexpireat/">Redis Documentation: HEXPIREAT</a>
* @since 3.5
*/
@@ -2449,9 +2446,8 @@ public interface StringRedisConnection extends RedisConnection {
* @param fields must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is in the past; {@code 1} indicating
* expiration time is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX |
* GT | LT condition is not met); {@code -2} indicating there is no such field; {@literal null} when used in
* pipeline / transaction.
* expiration time is set/updated; {@code 0} indicating the expiration time is not set; {@code -2} indicating
* there is no such field; {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hpexpireat/">Redis Documentation: HPEXPIREAT</a>
* @since 3.5
*/

View File

@@ -34,33 +34,30 @@ import org.springframework.lang.Nullable;
public interface BoundHashFieldExpirationOperations<HK> {
/**
* Apply {@link Expiration} to the hash without any additional constraints.
* Apply {@link Expiration} to the bound hash key/hash fields without any additional constraints.
*
* @param expiration the expiration definition.
* @return changes to the hash fields.
* @return changes to the hash fields. {@literal null} when used in pipeline / transaction.
*/
default ExpireChanges<HK> expire(Expiration expiration) {
return expire(expiration, Hash.FieldExpirationOptions.none());
}
/**
* Apply {@link Expiration} to the hash fields given {@link Hash.FieldExpirationOptions expiration options}.
* Apply {@link Expiration} to the bound hash key/hash fields given {@link Hash.FieldExpirationOptions expiration
* options}.
*
* @param expiration the expiration definition.
* @param options expiration options.
* @return changes to the hash fields.
* @return changes to the hash fields. {@literal null} when used in pipeline / transaction.
*/
ExpireChanges<HK> expire(Expiration expiration, Hash.FieldExpirationOptions options);
/**
* Set time to live for given {@code hashKey}.
* Set time to live for the bound hash key/hash fields.
*
* @param timeout the amount of time after which the key will be expired, must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration time
* is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX | GT | LT condition
* is not met); {@code -2} indicating there is no such field; {@literal null} when used in pipeline /
* transaction.
* @return changes to the hash fields. {@literal null} when used in pipeline / transaction.
* @throws IllegalArgumentException if the timeout is {@literal null}.
* @see <a href="https://redis.io/docs/latest/commands/hexpire/">Redis Documentation: HEXPIRE</a>
* @since 3.5
@@ -69,14 +66,10 @@ public interface BoundHashFieldExpirationOperations<HK> {
ExpireChanges<HK> expire(Duration timeout);
/**
* Set the expiration for given {@code hashKey} as a {@literal date} timestamp.
* Set the expiration for the bound hash key/hash fields as a {@literal date} timestamp.
*
* @param expireAt must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is in the past; {@code 1} indicating
* expiration time is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX |
* GT | LT condition is not met); {@code -2} indicating there is no such field; {@literal null} when used in
* pipeline / transaction.
* @return changes to the hash fields. {@literal null} when used in pipeline / transaction.
* @throws IllegalArgumentException if the instant is {@literal null} or too large to represent as a {@code Date}.
* @see <a href="https://redis.io/docs/latest/commands/hexpireat/">Redis Documentation: HEXPIRE</a>
* @since 3.5
@@ -85,11 +78,9 @@ public interface BoundHashFieldExpirationOperations<HK> {
ExpireChanges<HK> expireAt(Instant expireAt);
/**
* Remove the expiration from given {@code hashKey} .
* Remove the expiration from the bound hash key/hash fields.
*
* @return a list of {@link Long} values for each of the fields provided: {@code 1} indicating expiration time is
* removed; {@code -1} field has no expiration time to be removed; {@code -2} indicating there is no such
* field; {@literal null} when used in pipeline / transaction.
* @return changes to the hash fields. {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hpersist/">Redis Documentation: HPERSIST</a>
* @since 3.5
*/
@@ -97,12 +88,9 @@ public interface BoundHashFieldExpirationOperations<HK> {
ExpireChanges<HK> persist();
/**
* Get the time to live for {@code hashKey} in seconds.
* Get the time to live for bound hash key/hash fields in seconds.
*
* @return a list of {@link Long} values for each of the fields provided: the time to live in seconds; or a negative
* value to signal an error. The command returns {@code -1} if the key exists but has no associated expiration
* time. The command returns {@code -2} if the key does not exist; {@literal null} when used in pipeline /
* transaction.
* @return the actual expirations in seconds for the hash fields. {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/httl/">Redis Documentation: HTTL</a>
* @since 3.5
*/
@@ -110,12 +98,10 @@ public interface BoundHashFieldExpirationOperations<HK> {
Expirations<HK> getTimeToLive();
/**
* Get the time to live for {@code hashKey} and convert it to the given {@link TimeUnit}.
* Get the time to live for the bound hash key/hash fields and convert it to the given {@link TimeUnit}.
*
* @param timeUnit must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: the time to live in seconds; or a negative
* value to signal an error. The command returns {@code -1} if the key exists but has no associated expiration
* time. The command returns {@code -2} if the key does not exist; {@literal null} when used in pipeline /
* @return the actual expirations for the hash fields in the given time unit. {@literal null} when used in pipeline /
* transaction.
* @see <a href="https://redis.io/docs/latest/commands/httl/">Redis Documentation: HTTL</a>
* @since 3.5

View File

@@ -29,7 +29,6 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import org.reactivestreams.Publisher;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.redis.connection.Hash.FieldExpirationOptions;
import org.springframework.data.redis.connection.ReactiveHashCommands;
@@ -249,13 +248,14 @@ class DefaultReactiveHashOperations<H, HK, HV> implements ReactiveHashOperations
}
@Override
public Mono<ExpireChanges<HK>> expire(H key, Expiration expiration, FieldExpirationOptions options, Collection<HK> hashKeys) {
public Mono<ExpireChanges<HK>> expire(H key, Expiration expiration, FieldExpirationOptions options,
Collection<HK> hashKeys) {
List<HK> orderedKeys = List.copyOf(hashKeys);
ByteBuffer rawKey = rawKey(key);
List<ByteBuffer> rawHashKeys = orderedKeys.stream().map(this::rawHashKey).toList();
Mono<List<Long>> raw =createFlux(connection -> {
Mono<List<Long>> raw = createFlux(connection -> {
return connection
.applyExpiration(Mono.just(ExpireCommand.expire(rawHashKeys, expiration).from(rawKey).withOptions(options)))
.map(NumericResponse::getOutput);

View File

@@ -235,11 +235,7 @@ public interface HashOperations<H, HK, HV> {
* @param key must not be {@literal null}.
* @param timeout the amount of time after which the key will be expired, must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is 0; {@code 1} indicating expiration time
* is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX | GT | LT condition
* is not met); {@code -2} indicating there is no such field; {@literal null} when used in pipeline /
* transaction.
* @return changes to the hash fields. {@literal null} when used in pipeline / transaction.
* @throws IllegalArgumentException if the timeout is {@literal null}.
* @see <a href="https://redis.io/docs/latest/commands/hexpire/">Redis Documentation: HEXPIRE</a>
* @since 3.5
@@ -253,11 +249,7 @@ public interface HashOperations<H, HK, HV> {
* @param key must not be {@literal null}.
* @param expireAt must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is in the past; {@code 1} indicating
* expiration time is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX |
* GT | LT condition is not met); {@code -2} indicating there is no such field; {@literal null} when used in
* pipeline / transaction.
* @return changes to the hash fields. {@literal null} when used in pipeline / transaction.
* @throws IllegalArgumentException if the instant is {@literal null} or too large to represent as a {@code Date}.
* @see <a href="https://redis.io/docs/latest/commands/hexpireat/">Redis Documentation: HEXPIRE</a>
* @since 3.5
@@ -272,11 +264,7 @@ public interface HashOperations<H, HK, HV> {
* @param expiration must not be {@literal null}.
* @param options must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is in the past; {@code 1} indicating
* expiration time is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX |
* GT | LT condition is not met); {@code -2} indicating there is no such field; {@literal null} when used in
* pipeline / transaction.
* @return changes to the hash fields. {@literal null} when used in pipeline / transaction.
* @throws IllegalArgumentException if the instant is {@literal null} or too large to represent as a {@code Date}.
* @see <a href="https://redis.io/docs/latest/commands/hexpireat/">Redis Documentation: HEXPIRE</a>
* @since 3.5
@@ -289,9 +277,7 @@ public interface HashOperations<H, HK, HV> {
*
* @param key must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 1} indicating expiration time is
* removed; {@code -1} field has no expiration time to be removed; {@code -2} indicating there is no such
* field; {@literal null} when used in pipeline / transaction.
* @return changes to the hash fields. {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/hpersist/">Redis Documentation: HPERSIST</a>
* @since 3.5
*/
@@ -303,10 +289,7 @@ public interface HashOperations<H, HK, HV> {
*
* @param key must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: the time to live in seconds; or a negative
* value to signal an error. The command returns {@code -1} if the key exists but has no associated expiration
* time. The command returns {@code -2} if the key does not exist; {@literal null} when used in pipeline /
* transaction.
* @return the actual expirations in seconds for the hash fields. {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/httl/">Redis Documentation: HTTL</a>
* @since 3.5
*/
@@ -321,10 +304,7 @@ public interface HashOperations<H, HK, HV> {
* @param key must not be {@literal null}.
* @param timeUnit must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: the time to live in seconds; or a negative
* value to signal an error. The command returns {@code -1} if the key exists but has no associated expiration
* time. The command returns {@code -2} if the key does not exist; {@literal null} when used in pipeline /
* transaction.
* @return the actual expirations for the hash fields. {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/docs/latest/commands/httl/">Redis Documentation: HTTL</a>
* @since 3.5
*/

View File

@@ -238,8 +238,31 @@ public interface ReactiveHashOperations<H, HK, HV> {
*/
Flux<Map.Entry<HK, HV>> scan(H key, ScanOptions options);
/**
* Set time to live for given {@literal hashKeys} stored within {@literal key}.
*
* @param key must not be {@literal null}.
* @param timeout the amount of time after which the key will be expired, must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a {@link Mono} emitting changes to the hash fields.
* @throws IllegalArgumentException if the timeout is {@literal null}.
* @see <a href="https://redis.io/docs/latest/commands/hexpire/">Redis Documentation: HEXPIRE</a>
* @since 3.5
*/
Mono<ExpireChanges<HK>> expire(H key, Duration timeout, Collection<HK> hashKeys);
/**
* Set time to live for given {@literal hashKeys} stored within {@literal key}.
*
* @param key must not be {@literal null}.
* @param expiration must not be {@literal null}.
* @param options additional options to apply.
* @param hashKeys must not be {@literal null}.
* @return a {@link Mono} emitting changes to the hash fields.
* @throws IllegalArgumentException if the timeout is {@literal null}.
* @see <a href="https://redis.io/docs/latest/commands/hexpire/">Redis Documentation: HEXPIRE</a>
* @since 3.5
*/
Mono<ExpireChanges<HK>> expire(H key, Expiration expiration, FieldExpirationOptions options, Collection<HK> hashKeys);
/**
@@ -248,11 +271,7 @@ public interface ReactiveHashOperations<H, HK, HV> {
* @param key must not be {@literal null}.
* @param expireAt must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 2} indicating the specific field is
* deleted already due to expiration, or provided expiry interval is in the past; {@code 1} indicating
* expiration time is set/updated; {@code 0} indicating the expiration time is not set (a provided NX | XX |
* GT | LT condition is not met); {@code -2} indicating there is no such field; {@literal null} when used in
* pipeline / transaction.
* @return a {@link Mono} emitting changes to the hash fields.
* @throws IllegalArgumentException if the instant is {@literal null} or too large to represent as a {@code Date}.
* @see <a href="https://redis.io/docs/latest/commands/hexpireat/">Redis Documentation: HEXPIRE</a>
* @since 3.5
@@ -265,9 +284,7 @@ public interface ReactiveHashOperations<H, HK, HV> {
*
* @param key must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: {@code 1} indicating expiration time is
* removed; {@code -1} field has no expiration time to be removed; {@code -2} indicating there is no such
* field; {@literal null} when used in pipeline / transaction.
* @return a {@link Mono} emitting changes to the hash fields.
* @see <a href="https://redis.io/docs/latest/commands/hpersist/">Redis Documentation: HPERSIST</a>
* @since 3.5
*/
@@ -279,10 +296,7 @@ public interface ReactiveHashOperations<H, HK, HV> {
*
* @param key must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: the time to live in seconds; or a negative
* value to signal an error. The command returns {@code -1} if the key exists but has no associated expiration
* time. The command returns {@code -2} if the key does not exist; {@literal null} when used in pipeline /
* transaction.
* @return a {@link Mono} emitting {@link Expirations} of the hash fields.
* @see <a href="https://redis.io/docs/latest/commands/httl/">Redis Documentation: HTTL</a>
* @since 3.5
*/
@@ -297,10 +311,7 @@ public interface ReactiveHashOperations<H, HK, HV> {
* @param key must not be {@literal null}.
* @param timeUnit must not be {@literal null}.
* @param hashKeys must not be {@literal null}.
* @return a list of {@link Long} values for each of the fields provided: the time to live in seconds; or a negative
* value to signal an error. The command returns {@code -1} if the key exists but has no associated expiration
* time. The command returns {@code -2} if the key does not exist; {@literal null} when used in pipeline /
* transaction.
* @return a {@link Mono} emitting {@link Expirations} of the hash fields.
* @see <a href="https://redis.io/docs/latest/commands/httl/">Redis Documentation: HTTL</a>
* @since 3.5
*/

View File

@@ -376,7 +376,6 @@ public interface RedisOperations<K, V> {
@Nullable
Boolean persist(K key);
// TODO: Add TimeToLive (getTimeToLive)
/**
* Get the time to live for {@code key} in seconds.
*

View File

@@ -15,24 +15,48 @@
*/
package org.springframework.data.redis.connection;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assumptions.*;
import static org.awaitility.Awaitility.*;
import static org.junit.jupiter.api.condition.OS.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldIncrBy.Overflow.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.*;
import static org.springframework.data.redis.connection.ClusterTestVariables.*;
import static org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit.*;
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.*;
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchStoreCommandArgs.*;
import static org.springframework.data.redis.core.ScanOptions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.Assertions.within;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.condition.OS.MAC;
import static org.springframework.data.redis.connection.BitFieldSubCommands.create;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldIncrBy.Overflow.FAIL;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.INT_8;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.signed;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.unsigned;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_1;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_2;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_3;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_1;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_2;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_3;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_4;
import static org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit.KILOMETERS;
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs;
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.newGeoSearchArgs;
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoSearchStoreCommandArgs.newGeoSearchStoreArgs;
import static org.springframework.data.redis.core.ScanOptions.scanOptions;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
@@ -753,7 +777,7 @@ public abstract class AbstractConnectionIntegrationTests {
assertThat(stringSerializer.deserialize((byte[]) getResults().get(1))).isEqualTo("bar");
}
@Test
@Test // GH-
@EnabledOnCommand("HEXPIRE")
void testExecuteHashFieldExpiration() {
@@ -3473,7 +3497,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(new Object[] { 0L }));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireReturnsSuccessAndSetsTTL() {
@@ -3484,10 +3508,10 @@ public abstract class AbstractConnectionIntegrationTests {
List<Object> results = getResults();
assertThat(results.get(0)).isEqualTo(Boolean.TRUE);
assertThat((List) results.get(1)).contains(1L);
assertThat((List) results.get(2)).allSatisfy( value -> assertThat((Long)value).isBetween(0L, 5L));
assertThat((List) results.get(2)).allSatisfy(value -> assertThat((Long) value).isBetween(0L, 5L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireReturnsMinusTwoWhenFieldDoesNotExist() {
@@ -3498,7 +3522,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(-2L), List.of(-2L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireReturnsTwoWhenZeroProvided() {
@@ -3508,7 +3532,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(2L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HPEXPIRE")
public void hpExpireReturnsSuccessAndSetsTTL() {
@@ -3519,10 +3543,10 @@ public abstract class AbstractConnectionIntegrationTests {
List<Object> results = getResults();
assertThat(results.get(0)).isEqualTo(Boolean.TRUE);
assertThat((List) results.get(1)).contains(1L);
assertThat((List) results.get(2)).allSatisfy( value -> assertThat((Long)value).isBetween(0L, 5000L));
assertThat((List) results.get(2)).allSatisfy(value -> assertThat((Long) value).isBetween(0L, 5000L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HPEXPIRE")
public void hpExpireReturnsMinusTwoWhenFieldDoesNotExist() {
@@ -3533,7 +3557,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(-2L), List.of(-2L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HPEXPIRE")
public void hpExpireReturnsTwoWhenZeroProvided() {
@@ -3543,7 +3567,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(2L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIREAT")
public void hExpireAtReturnsSuccessAndSetsTTL() {
@@ -3556,10 +3580,10 @@ public abstract class AbstractConnectionIntegrationTests {
List<Object> results = getResults();
assertThat(results.get(0)).isEqualTo(Boolean.TRUE);
assertThat((List) results.get(1)).contains(1L);
assertThat((List) results.get(2)).allSatisfy( value -> assertThat((Long)value).isBetween(0L, 5L));
assertThat((List) results.get(2)).allSatisfy(value -> assertThat((Long) value).isBetween(0L, 5L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIREAT")
public void hExpireAtReturnsMinusTwoWhenFieldDoesNotExist() {
@@ -3572,7 +3596,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(-2L), List.of(-2L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIREAT")
public void hExpireAtReturnsTwoWhenZeroProvided() {
@@ -3584,7 +3608,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(2L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIREAT")
public void hpExpireAtReturnsSuccessAndSetsTTL() {
@@ -3597,10 +3621,10 @@ public abstract class AbstractConnectionIntegrationTests {
List<Object> results = getResults();
assertThat(results.get(0)).isEqualTo(Boolean.TRUE);
assertThat((List) results.get(1)).contains(1L);
assertThat((List) results.get(2)).allSatisfy( value -> assertThat((Long)value).isBetween(0L, 5L));
assertThat((List) results.get(2)).allSatisfy(value -> assertThat((Long) value).isBetween(0L, 5L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIREAT")
public void hpExpireAtReturnsMinusTwoWhenFieldDoesNotExist() {
@@ -3613,7 +3637,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(-2L), List.of(-2L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HPEXPIREAT")
public void hpExpireAdReturnsTwoWhenZeroProvided() {
@@ -3625,7 +3649,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(2L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HPERSIST")
public void hPersistReturnsSuccessAndPersistsField() {
@@ -3637,7 +3661,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(1L), List.of(1L), List.of(-1L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HPERSIST")
public void hPersistReturnsMinusOneWhenFieldDoesNotHaveExpiration() {
@@ -3647,7 +3671,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(-1L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HPERSIST")
public void hPersistReturnsMinusTwoWhenFieldOrKeyMissing() {
@@ -3658,7 +3682,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(-2L), List.of(-2L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HTTL")
public void hTtlReturnsMinusOneWhenFieldHasNoExpiration() {
@@ -3668,7 +3692,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(-1L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HTTL")
public void hTtlReturnsMinusIndependendOfTimeUnitOneWhenFieldHasNoExpiration() {
@@ -3678,7 +3702,7 @@ public abstract class AbstractConnectionIntegrationTests {
verifyResults(Arrays.asList(Boolean.TRUE, List.of(-1L)));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HTTL")
public void hTtlReturnsMinusTwoWhenFieldOrKeyMissing() {

View File

@@ -15,17 +15,37 @@
*/
package org.springframework.data.redis.connection.jedis;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.data.Offset.offset;
import static org.springframework.data.redis.connection.BitFieldSubCommands.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldIncrBy.Overflow.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.*;
import static org.springframework.data.redis.connection.ClusterTestVariables.*;
import static org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit.*;
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.*;
import static org.springframework.data.redis.connection.RedisListCommands.*;
import static org.springframework.data.redis.connection.RedisZSetCommands.*;
import static org.springframework.data.redis.core.ScanOptions.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.create;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldIncrBy.Overflow.FAIL;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.INT_8;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.signed;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.unsigned;
import static org.springframework.data.redis.connection.ClusterTestVariables.CLUSTER_HOST;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_1;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_2;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_3;
import static org.springframework.data.redis.connection.ClusterTestVariables.MASTER_NODE_1_PORT;
import static org.springframework.data.redis.connection.ClusterTestVariables.MASTER_NODE_2_PORT;
import static org.springframework.data.redis.connection.ClusterTestVariables.MASTER_NODE_3_PORT;
import static org.springframework.data.redis.connection.ClusterTestVariables.REPLICAOF_NODE_1_PORT;
import static org.springframework.data.redis.connection.ClusterTestVariables.SAME_SLOT_KEY_1;
import static org.springframework.data.redis.connection.ClusterTestVariables.SAME_SLOT_KEY_2;
import static org.springframework.data.redis.connection.ClusterTestVariables.SAME_SLOT_KEY_3;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_1;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_2;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_3;
import static org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit.KILOMETERS;
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs;
import static org.springframework.data.redis.connection.RedisListCommands.Direction;
import static org.springframework.data.redis.connection.RedisListCommands.Position;
import static org.springframework.data.redis.connection.RedisZSetCommands.Range;
import static org.springframework.data.redis.core.ScanOptions.NONE;
import static org.springframework.data.redis.core.ScanOptions.scanOptions;
import redis.clients.jedis.ConnectionPool;
import redis.clients.jedis.HostAndPort;
@@ -37,14 +57,23 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Range.Bound;
@@ -1040,9 +1069,10 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hStrLen(KEY_1_BYTES, KEY_1_BYTES)).isEqualTo(0L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireReturnsSuccessAndSetsTTL() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hExpire(KEY_1_BYTES, 5L, KEY_2_BYTES)).contains(1L);
@@ -1050,9 +1080,10 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
.allSatisfy(val -> assertThat(val).isBetween(0L, 5L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireReturnsMinusTwoWhenFieldDoesNotExist() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
// missing field
assertThat(clusterConnection.hashCommands().hExpire(KEY_1_BYTES, 5L, KEY_1_BYTES)).contains(-2L);
@@ -1060,27 +1091,30 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hExpire(KEY_2_BYTES, 5L, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireReturnsTwoWhenZeroProvided() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hExpire(KEY_1_BYTES, 0L, KEY_2_BYTES)).contains(2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireReturnsSuccessAndSetsTTL() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hpExpire(KEY_1_BYTES, 5000L, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, TimeUnit.MILLISECONDS,KEY_2_BYTES))
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, TimeUnit.MILLISECONDS, KEY_2_BYTES))
.allSatisfy(val -> assertThat(val).isBetween(0L, 5000L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireReturnsMinusTwoWhenFieldDoesNotExist() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
// missing field
assertThat(clusterConnection.hashCommands().hpExpire(KEY_1_BYTES, 5L, KEY_1_BYTES)).contains(-2L);
@@ -1088,26 +1122,31 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hpExpire(KEY_2_BYTES, 5L, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireReturnsTwoWhenZeroProvided() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hpExpire(KEY_1_BYTES, 0L, KEY_2_BYTES)).contains(2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireAtReturnsSuccessAndSetsTTL() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
long inFiveSeconds = Instant.now().plusSeconds(5L).getEpochSecond();
assertThat(clusterConnection.hashCommands().hExpireAt(KEY_1_BYTES, inFiveSeconds, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, KEY_2_BYTES)).allSatisfy(val -> assertThat(val).isBetween(0L, 5L));
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, KEY_2_BYTES))
.allSatisfy(val -> assertThat(val).isBetween(0L, 5L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireAtReturnsMinusTwoWhenFieldDoesNotExist() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
long inFiveSeconds = Instant.now().plusSeconds(5L).getEpochSecond();
@@ -1117,27 +1156,31 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hExpireAt(KEY_2_BYTES, inFiveSeconds, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireAdReturnsTwoWhenZeroProvided() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hExpireAt(KEY_1_BYTES, 0L, KEY_2_BYTES)).contains(2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireAtReturnsSuccessAndSetsTTL() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
long inFiveSeconds = Instant.now().plusSeconds(5L).toEpochMilli();
assertThat(clusterConnection.hashCommands().hpExpireAt(KEY_1_BYTES, inFiveSeconds, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, TimeUnit.MILLISECONDS, KEY_2_BYTES))
.allSatisfy(val -> assertThat(val).isBetween(0L, 5000L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireAtReturnsMinusTwoWhenFieldDoesNotExist() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
long inFiveSeconds = Instant.now().plusSeconds(5L).toEpochMilli();
@@ -1147,55 +1190,60 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hpExpireAt(KEY_2_BYTES, inFiveSeconds, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireAdReturnsTwoWhenZeroProvided() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hpExpireAt(KEY_1_BYTES, 0L, KEY_2_BYTES)).contains(2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hPersistReturnsSuccessAndPersistsField() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hExpire(KEY_1_BYTES, 5L, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hashCommands().hPersist(KEY_1_BYTES, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hashCommands().hPersist(KEY_1_BYTES, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, KEY_2_BYTES)).contains(-1L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hPersistReturnsMinusOneWhenFieldDoesNotHaveExpiration() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hPersist(KEY_1_BYTES, KEY_2_BYTES)).contains(-1L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hPersistReturnsMinusTwoWhenFieldOrKeyMissing() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hPersist(KEY_1_BYTES, KEY_1_BYTES)).contains(-2L);
assertThat(clusterConnection.hashCommands().hPersist(KEY_3_BYTES,KEY_2_BYTES)).contains(-2L);
assertThat(clusterConnection.hashCommands().hPersist(KEY_3_BYTES, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hTtlReturnsMinusOneWhenFieldHasNoExpiration() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, KEY_2_BYTES)).contains(-1L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hTtlReturnsMinusTwoWhenFieldOrKeyMissing() {
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, KEY_1_BYTES)).contains(-2L);
assertThat(clusterConnection.hashCommands().hTtl(KEY_3_BYTES,KEY_2_BYTES)).contains(-2L);
assertThat(clusterConnection.hashCommands().hTtl(KEY_3_BYTES, KEY_2_BYTES)).contains(-2L);
}
@Test // DATAREDIS-315
@@ -1346,7 +1394,7 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
.isEqualTo(VALUE_2_BYTES);
assertThat(
clusterConnection.bLMove(SAME_SLOT_KEY_1_BYTES, SAME_SLOT_KEY_2_BYTES, Direction.RIGHT, Direction.LEFT, 0.01))
.isNull();
.isNull();
assertThat(nativeConnection.lrange(SAME_SLOT_KEY_1, 0, -1)).isEmpty();
assertThat(nativeConnection.lrange(SAME_SLOT_KEY_2, 0, -1)).containsExactly(VALUE_2, VALUE_3);
@@ -2946,13 +2994,13 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.stringCommands().bitField(JedisConverters.toBytes(KEY_1),
create().incr(unsigned(2)).valueAt(BitFieldSubCommands.Offset.offset(102L)).overflow(FAIL).by(1L)))
.containsExactly(1L);
.containsExactly(1L);
assertThat(clusterConnection.stringCommands().bitField(JedisConverters.toBytes(KEY_1),
create().incr(unsigned(2)).valueAt(BitFieldSubCommands.Offset.offset(102L)).overflow(FAIL).by(1L)))
.containsExactly(2L);
.containsExactly(2L);
assertThat(clusterConnection.stringCommands().bitField(JedisConverters.toBytes(KEY_1),
create().incr(unsigned(2)).valueAt(BitFieldSubCommands.Offset.offset(102L)).overflow(FAIL).by(1L)))
.containsExactly(3L);
.containsExactly(3L);
assertThat(clusterConnection.stringCommands()
.bitField(JedisConverters.toBytes(KEY_1),
create().incr(unsigned(2)).valueAt(BitFieldSubCommands.Offset.offset(102L)).overflow(FAIL).by(1L))
@@ -2964,7 +3012,7 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.stringCommands().bitField(JedisConverters.toBytes(KEY_1),
create().incr(signed(5)).valueAt(BitFieldSubCommands.Offset.offset(100L)).by(1L).get(unsigned(4)).valueAt(0L)))
.containsExactly(1L, 0L);
.containsExactly(1L, 0L);
}
@Test // DATAREDIS-562
@@ -2974,13 +3022,13 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
clusterConnection.stringCommands().bitField(JedisConverters.toBytes(KEY_1),
create().set(INT_8).valueAt(BitFieldSubCommands.Offset.offset(0L).multipliedByTypeLength()).to(100L)
.set(INT_8).valueAt(BitFieldSubCommands.Offset.offset(1L).multipliedByTypeLength()).to(200L)))
.containsExactly(0L, 0L);
.containsExactly(0L, 0L);
assertThat(
clusterConnection.stringCommands()
.bitField(JedisConverters.toBytes(KEY_1),
create().get(INT_8).valueAt(BitFieldSubCommands.Offset.offset(0L).multipliedByTypeLength()).get(INT_8)
.valueAt(BitFieldSubCommands.Offset.offset(1L).multipliedByTypeLength()))).containsExactly(100L,
-56L);
.valueAt(BitFieldSubCommands.Offset.offset(1L).multipliedByTypeLength())))
.containsExactly(100L, -56L);
}
@Test // DATAREDIS-1005
@@ -3125,7 +3173,8 @@ public class JedisClusterConnectionTests implements ClusterConnectionTests {
assertThat(topology).isInstanceOf(JedisClusterConnection.JedisClusterTopology.class);
assertThat(provider.shouldUseCachedValue(null)).isFalse();
assertThat(provider.shouldUseCachedValue(new JedisClusterConnection.JedisClusterTopology(Set.of(), System.currentTimeMillis() - 101, 100))).isFalse();
assertThat(provider.shouldUseCachedValue(
new JedisClusterConnection.JedisClusterTopology(Set.of(), System.currentTimeMillis() - 101, 100))).isFalse();
assertThat(provider.shouldUseCachedValue(
new JedisClusterConnection.JedisClusterTopology(Set.of(), System.currentTimeMillis() + 100, 100))).isTrue();
}

View File

@@ -15,16 +15,35 @@
*/
package org.springframework.data.redis.connection.lettuce;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.data.Offset.offset;
import static org.springframework.data.redis.connection.BitFieldSubCommands.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldIncrBy.Overflow.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.*;
import static org.springframework.data.redis.connection.ClusterTestVariables.*;
import static org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit.*;
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.*;
import static org.springframework.data.redis.connection.RedisZSetCommands.*;
import static org.springframework.data.redis.core.ScanOptions.*;
import static org.springframework.data.redis.connection.BitFieldSubCommands.create;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldIncrBy.Overflow.FAIL;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.INT_8;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.signed;
import static org.springframework.data.redis.connection.BitFieldSubCommands.BitFieldType.unsigned;
import static org.springframework.data.redis.connection.ClusterTestVariables.CLUSTER_HOST;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_1;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_2;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_3;
import static org.springframework.data.redis.connection.ClusterTestVariables.KEY_4;
import static org.springframework.data.redis.connection.ClusterTestVariables.MASTER_NODE_1_PORT;
import static org.springframework.data.redis.connection.ClusterTestVariables.MASTER_NODE_2_PORT;
import static org.springframework.data.redis.connection.ClusterTestVariables.MASTER_NODE_3_PORT;
import static org.springframework.data.redis.connection.ClusterTestVariables.REPLICAOF_NODE_1_PORT;
import static org.springframework.data.redis.connection.ClusterTestVariables.SAME_SLOT_KEY_1;
import static org.springframework.data.redis.connection.ClusterTestVariables.SAME_SLOT_KEY_2;
import static org.springframework.data.redis.connection.ClusterTestVariables.SAME_SLOT_KEY_3;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_1;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_2;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_3;
import static org.springframework.data.redis.connection.ClusterTestVariables.VALUE_4;
import static org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit.KILOMETERS;
import static org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs;
import static org.springframework.data.redis.connection.RedisZSetCommands.Range;
import static org.springframework.data.redis.core.ScanOptions.scanOptions;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands;
@@ -33,7 +52,17 @@ import io.lettuce.core.codec.ByteArrayCodec;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.assertj.core.data.Offset;
@@ -49,11 +78,21 @@ import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.connection.ClusterConnectionTests;
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
import org.springframework.data.redis.connection.ClusterTestVariables;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.DefaultSortParameters;
import org.springframework.data.redis.connection.Limit;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisClusterConnection;
import org.springframework.data.redis.connection.RedisClusterNode;
import org.springframework.data.redis.connection.RedisClusterNode.SlotRange;
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
import org.springframework.data.redis.connection.RedisListCommands;
import org.springframework.data.redis.connection.RedisListCommands.Position;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisServerCommands.FlushOption;
import org.springframework.data.redis.connection.RedisStringCommands.BitOperation;
import org.springframework.data.redis.connection.RedisStringCommands.SetOption;
@@ -1097,7 +1136,7 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hStrLen(KEY_1_BYTES, KEY_1_BYTES)).isEqualTo(0L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireReturnsSuccessAndSetsTTL() {
@@ -1107,7 +1146,7 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hTtl(KEY_1_BYTES, KEY_2_BYTES)).allSatisfy(val -> assertThat(val).isBetween(0L, 5L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireReturnsMinusTwoWhenFieldDoesNotExist() {
@@ -1118,17 +1157,19 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hExpire(KEY_2_BYTES, 5L, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireReturnsTwoWhenZeroProvided() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hExpire(KEY_1_BYTES, 0L, KEY_2_BYTES)).contains(2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireReturnsSuccessAndSetsTTL() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hpExpire(KEY_1_BYTES, 5000L, KEY_2_BYTES)).contains(1L);
@@ -1136,7 +1177,7 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
.allSatisfy(val -> assertThat(val).isBetween(0L, 5000L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireReturnsMinusTwoWhenFieldDoesNotExist() {
@@ -1147,7 +1188,7 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hpExpire(KEY_2_BYTES, 5L, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireReturnsTwoWhenZeroProvided() {
@@ -1156,17 +1197,18 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hpExpire(KEY_1_BYTES, 0L, KEY_2_BYTES)).contains(2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireAtReturnsSuccessAndSetsTTL() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
long inFiveSeconds = Instant.now().plusSeconds(5L).getEpochSecond();
assertThat(clusterConnection.hashCommands().hExpireAt(KEY_1_BYTES, inFiveSeconds, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hTtl(KEY_1_BYTES, KEY_2_BYTES)).allSatisfy(val -> assertThat(val).isBetween(0L, 5L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireAtReturnsMinusTwoWhenFieldDoesNotExist() {
@@ -1180,9 +1222,10 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hExpireAt(KEY_2_BYTES, inFiveSeconds, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hExpireAdReturnsTwoWhenZeroProvided() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hExpireAt(KEY_1_BYTES, 0L, KEY_2_BYTES)).contains(2L);
@@ -1194,12 +1237,13 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
long inFiveSeconds = Instant.now().plusSeconds(5L).toEpochMilli();
assertThat(clusterConnection.hashCommands().hpExpireAt(KEY_1_BYTES, inFiveSeconds, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hpTtl(KEY_1_BYTES, KEY_2_BYTES))
.allSatisfy(val -> assertThat(val).isGreaterThan(1000L).isLessThanOrEqualTo(5000L));
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireAtReturnsMinusTwoWhenFieldDoesNotExist() {
@@ -1212,7 +1256,7 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hpExpireAt(KEY_2_BYTES, inFiveSeconds, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hpExpireAdReturnsTwoWhenZeroProvided() {
@@ -1221,17 +1265,17 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hpExpireAt(KEY_1_BYTES, 0L, KEY_2_BYTES)).contains(2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hPersistReturnsSuccessAndPersistsField() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hExpire(KEY_1_BYTES, 5L, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hashCommands().hPersist(KEY_1_BYTES, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hashCommands().hPersist(KEY_1_BYTES, KEY_2_BYTES)).contains(1L);
assertThat(clusterConnection.hTtl(KEY_1_BYTES, KEY_2_BYTES)).contains(-1L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hPersistReturnsMinusOneWhenFieldDoesNotHaveExpiration() {
@@ -1239,17 +1283,18 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hPersist(KEY_1_BYTES, KEY_2_BYTES)).contains(-1L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hPersistReturnsMinusTwoWhenFieldOrKeyMissing() {
nativeConnection.hset(KEY_1, KEY_2, VALUE_3);
assertThat(clusterConnection.hashCommands().hPersist(KEY_1_BYTES, KEY_1_BYTES)).contains(-2L);
assertThat(clusterConnection.hashCommands().hPersist(KEY_3_BYTES,KEY_2_BYTES)).contains(-2L);
assertThat(clusterConnection.hashCommands().hPersist(KEY_3_BYTES, KEY_2_BYTES)).contains(-2L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hTtlReturnsMinusOneWhenFieldHasNoExpiration() {
@@ -1259,12 +1304,12 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, TimeUnit.HOURS, KEY_2_BYTES)).contains(-1L);
}
@Test
@Test // GH-3054
@EnabledOnCommand("HEXPIRE")
public void hTtlReturnsMinusTwoWhenFieldOrKeyMissing() {
assertThat(clusterConnection.hashCommands().hTtl(KEY_1_BYTES, KEY_1_BYTES)).contains(-2L);
assertThat(clusterConnection.hashCommands().hTtl(KEY_3_BYTES,KEY_2_BYTES)).contains(-2L);
assertThat(clusterConnection.hashCommands().hTtl(KEY_3_BYTES, KEY_2_BYTES)).contains(-2L);
}
@Test // DATAREDIS-315

View File

@@ -15,9 +15,8 @@
*/
package org.springframework.data.redis.connection.lettuce;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import org.springframework.data.redis.test.condition.EnabledOnCommand;
import reactor.test.StepVerifier;
import java.nio.ByteBuffer;
@@ -31,6 +30,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.test.condition.EnabledOnCommand;
import org.springframework.data.redis.test.extension.parametrized.ParameterizedRedisTest;
/**
@@ -107,8 +107,7 @@ public class LettuceReactiveHashCommandsIntegrationTests extends LettuceReactive
nativeCommands.hset(KEY_1, FIELD_3, VALUE_3);
connection.hashCommands().hMGet(KEY_1_BBUFFER, Arrays.asList(FIELD_1_BBUFFER, FIELD_3_BBUFFER))
.as(StepVerifier::create)
.consumeNextWith(actual -> {
.as(StepVerifier::create).consumeNextWith(actual -> {
assertThat(actual).contains(VALUE_1_BBUFFER, VALUE_3_BBUFFER);
@@ -124,13 +123,11 @@ public class LettuceReactiveHashCommandsIntegrationTests extends LettuceReactive
connection.hashCommands().hMGet(KEY_1_BBUFFER, Collections.singletonList(FIELD_1_BBUFFER)).as(StepVerifier::create)
.expectNext(Collections.singletonList(VALUE_1_BBUFFER)).verifyComplete();
connection.hashCommands().hMGet(KEY_1_BBUFFER, Collections.singletonList(FIELD_2_BBUFFER))
.as(StepVerifier::create)
connection.hashCommands().hMGet(KEY_1_BBUFFER, Collections.singletonList(FIELD_2_BBUFFER)).as(StepVerifier::create)
.expectNext(Collections.singletonList(null)).verifyComplete();
connection.hashCommands().hMGet(KEY_1_BBUFFER, Arrays.asList(FIELD_1_BBUFFER, FIELD_2_BBUFFER, FIELD_3_BBUFFER))
.as(StepVerifier::create)
.expectNext(Arrays.asList(VALUE_1_BBUFFER, null, VALUE_3_BBUFFER)).verifyComplete();
.as(StepVerifier::create).expectNext(Arrays.asList(VALUE_1_BBUFFER, null, VALUE_3_BBUFFER)).verifyComplete();
}
@ParameterizedRedisTest // DATAREDIS-525
@@ -197,8 +194,7 @@ public class LettuceReactiveHashCommandsIntegrationTests extends LettuceReactive
nativeCommands.hset(KEY_1, FIELD_3, VALUE_3);
connection.hashCommands().hDel(KEY_1_BBUFFER, Arrays.asList(FIELD_1_BBUFFER, FIELD_3_BBUFFER))
.as(StepVerifier::create)
.expectNext(2L).verifyComplete();
.as(StepVerifier::create).expectNext(2L).verifyComplete();
}
@ParameterizedRedisTest // DATAREDIS-525
@@ -293,62 +289,50 @@ public class LettuceReactiveHashCommandsIntegrationTests extends LettuceReactive
.verifyComplete();
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void hExpireShouldHandleMultipleParametersCorrectly() {
assertThat(nativeCommands.hset(KEY_1, FIELD_1, VALUE_1)).isTrue();
assertThat(nativeCommands.hset(KEY_1, FIELD_2, VALUE_2)).isTrue();
final var fields = Arrays.asList(FIELD_1_BBUFFER, FIELD_2_BBUFFER, FIELD_3_BBUFFER);
connection.hashCommands().hExpire(KEY_1_BBUFFER, Duration.ofSeconds(1), fields).as(StepVerifier::create) //
.expectNext(1L)
.expectNext(1L)
.expectNext(-2L)
.expectComplete()
.verify();
.expectNext(1L).expectNext(1L).expectNext(-2L).expectComplete().verify();
assertThat(nativeCommands.httl(KEY_1, FIELD_1)).allSatisfy(it -> assertThat(it).isBetween(0L, 1000L));
assertThat(nativeCommands.httl(KEY_1, FIELD_2)).allSatisfy(it -> assertThat(it).isBetween(0L, 1000L));
assertThat(nativeCommands.httl(KEY_1, FIELD_3)).allSatisfy(it -> assertThat(it).isEqualTo(-2L));
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void hExpireAtShouldHandleMultipleParametersCorrectly() {
assertThat(nativeCommands.hset(KEY_1, FIELD_1, VALUE_1)).isTrue();
assertThat(nativeCommands.hset(KEY_1, FIELD_2, VALUE_2)).isTrue();
final var fields = Arrays.asList(FIELD_1_BBUFFER, FIELD_2_BBUFFER, FIELD_3_BBUFFER);
connection.hashCommands().hExpireAt(KEY_1_BBUFFER, Instant.now().plusSeconds(1), fields).as(StepVerifier::create) //
.expectNext(1L)
.expectNext(1L)
.expectNext(-2L)
.expectComplete()
.verify();
.expectNext(1L).expectNext(1L).expectNext(-2L).expectComplete().verify();
assertThat(nativeCommands.httl(KEY_1, FIELD_1, FIELD_2)).allSatisfy(it -> assertThat(it).isBetween(0L, 1000L));
assertThat(nativeCommands.httl(KEY_1, FIELD_3)).allSatisfy(it -> assertThat(it).isEqualTo(-2L));
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void hPersistShouldPersistFields() {
assertThat(nativeCommands.hset(KEY_1, FIELD_1, VALUE_1)).isTrue();
assertThat(nativeCommands.hset(KEY_1, FIELD_2, VALUE_2)).isTrue();
assertThat(nativeCommands.hexpire(KEY_1, 1000, FIELD_1))
.allSatisfy(it -> assertThat(it).isEqualTo(1L));
assertThat(nativeCommands.hexpire(KEY_1, 1000, FIELD_1)).allSatisfy(it -> assertThat(it).isEqualTo(1L));
final var fields = Arrays.asList(FIELD_1_BBUFFER, FIELD_2_BBUFFER, FIELD_3_BBUFFER);
connection.hashCommands().hPersist(KEY_1_BBUFFER, fields).as(StepVerifier::create) //
.expectNext(1L)
.expectNext(-1L)
.expectNext(-2L)
.expectComplete()
.verify();
.expectNext(1L).expectNext(-1L).expectNext(-2L).expectComplete().verify();
assertThat(nativeCommands.httl(KEY_1, FIELD_1, FIELD_2)).allSatisfy(it -> assertThat(it).isEqualTo(-1L));
}

View File

@@ -15,8 +15,9 @@
*/
package org.springframework.data.redis.core;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assumptions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assumptions.assumeThat;
import java.io.IOException;
import java.time.Duration;
@@ -29,7 +30,6 @@ import java.util.concurrent.TimeUnit;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.data.redis.ObjectFactory;
import org.springframework.data.redis.RawObjectFactory;
import org.springframework.data.redis.StringObjectFactory;
@@ -212,7 +212,7 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
assertThat(values).hasSize(2).containsEntry(key1, val1).containsEntry(key2, val2);
}
@EnabledOnCommand("HEXPIRE")
@EnabledOnCommand("HEXPIRE") // GH-3054
@ParameterizedRedisTest
void testExpireAndGetExpireMillis() {
@@ -237,7 +237,7 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
});
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testExpireAndGetExpireSeconds() {
@@ -268,7 +268,7 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
});
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testBoundExpireAndGetExpireSeconds() {
@@ -300,7 +300,7 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
});
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testExpireAtAndGetExpireMillis() {
@@ -325,7 +325,7 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
});
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void expireThrowsErrorOfNanoPrecision() {
@@ -336,7 +336,7 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
.isThrownBy(() -> redisTemplate.opsForHash().getTimeToLive(key, TimeUnit.NANOSECONDS, List.of(key1)));
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testExpireWithOptionsNone() {
@@ -349,12 +349,13 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
hashOps.put(key, key1, val1);
hashOps.put(key, key2, val2);
ExpireChanges<Object> expire = redisTemplate.opsForHash().expire(key, org.springframework.data.redis.core.types.Expiration.seconds(20), FieldExpirationOptions.none(), List.of(key1));
ExpireChanges<Object> expire = redisTemplate.opsForHash().expire(key,
org.springframework.data.redis.core.types.Expiration.seconds(20), FieldExpirationOptions.none(), List.of(key1));
assertThat(expire.allOk()).isTrue();
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testExpireWithOptions() {
@@ -367,16 +368,20 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
hashOps.put(key, key1, val1);
hashOps.put(key, key2, val2);
redisTemplate.opsForHash().expire(key, org.springframework.data.redis.core.types.Expiration.seconds(20), FieldExpirationOptions.none(), List.of(key1));
redisTemplate.opsForHash().expire(key, org.springframework.data.redis.core.types.Expiration.seconds(60), FieldExpirationOptions.none(), List.of(key2));
redisTemplate.opsForHash().expire(key, org.springframework.data.redis.core.types.Expiration.seconds(20),
FieldExpirationOptions.none(), List.of(key1));
redisTemplate.opsForHash().expire(key, org.springframework.data.redis.core.types.Expiration.seconds(60),
FieldExpirationOptions.none(), List.of(key2));
ExpireChanges<Object> changes = redisTemplate.opsForHash().expire(key, org.springframework.data.redis.core.types.Expiration.seconds(30), FieldExpirationOptions.builder().gt().build(), List.of(key1, key2));
ExpireChanges<Object> changes = redisTemplate.opsForHash().expire(key,
org.springframework.data.redis.core.types.Expiration.seconds(30), FieldExpirationOptions.builder().gt().build(),
List.of(key1, key2));
assertThat(changes.ok()).containsExactly(key1);
assertThat(changes.skipped()).containsExactly(key2);
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testPersistAndGetExpireMillis() {

View File

@@ -15,9 +15,9 @@
*/
package org.springframework.data.redis.core;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assumptions.*;
import static org.junit.jupiter.api.condition.OS.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.junit.jupiter.api.condition.OS.MAC;
import reactor.test.StepVerifier;
@@ -33,7 +33,6 @@ import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.springframework.data.redis.ObjectFactory;
import org.springframework.data.redis.RawObjectFactory;
import org.springframework.data.redis.SettingsUtils;
@@ -506,7 +505,7 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
.verifyComplete();
}
@EnabledOnCommand("HEXPIRE")
@EnabledOnCommand("HEXPIRE") // GH-3054
@ParameterizedRedisTest
void testExpireAndGetExpireMillis() {
@@ -531,7 +530,7 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
}).verifyComplete();
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testExpireWithOptions() {
@@ -543,23 +542,32 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
putAll(key, key1, val1, key2, val2);
hashOperations.expire(key, org.springframework.data.redis.core.types.Expiration.seconds(20), FieldExpirationOptions.none(), List.of(key1)).as(StepVerifier::create)//
.assertNext(changes -> {
assertThat(changes.allOk()).isTrue();
}).verifyComplete();
hashOperations.expire(key, org.springframework.data.redis.core.types.Expiration.seconds(60), FieldExpirationOptions.none(), List.of(key2)).as(StepVerifier::create)//
.assertNext(changes -> {
assertThat(changes.allOk()).isTrue();
}).verifyComplete();
hashOperations
.expire(key, org.springframework.data.redis.core.types.Expiration.seconds(20), FieldExpirationOptions.none(),
List.of(key1))
.as(StepVerifier::create)//
.assertNext(changes -> {
assertThat(changes.allOk()).isTrue();
}).verifyComplete();
hashOperations
.expire(key, org.springframework.data.redis.core.types.Expiration.seconds(60), FieldExpirationOptions.none(),
List.of(key2))
.as(StepVerifier::create)//
.assertNext(changes -> {
assertThat(changes.allOk()).isTrue();
}).verifyComplete();
hashOperations.expire(key, org.springframework.data.redis.core.types.Expiration.seconds(30), FieldExpirationOptions.builder().gt().build(), List.of(key1, key2)).as(StepVerifier::create)//
.assertNext(changes -> {
assertThat(changes.ok()).containsExactly(key1);
assertThat(changes.skipped()).containsExactly(key2);
}).verifyComplete();
hashOperations
.expire(key, org.springframework.data.redis.core.types.Expiration.seconds(30),
FieldExpirationOptions.builder().gt().build(), List.of(key1, key2))
.as(StepVerifier::create)//
.assertNext(changes -> {
assertThat(changes.ok()).containsExactly(key1);
assertThat(changes.skipped()).containsExactly(key2);
}).verifyComplete();
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testExpireAndGetExpireSeconds() {
@@ -583,10 +591,9 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
assertThat(it.expirationOf(key1).raw()).isBetween(0L, 5L);
assertThat(it.expirationOf(key2).raw()).isBetween(0L, 5L);
}).verifyComplete();
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testExpireAtAndGetExpireMillis() {
@@ -611,7 +618,7 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
}).verifyComplete();
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testPersistAndGetExpireMillis() {
@@ -638,7 +645,6 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
.assertNext(expirations -> {
assertThat(expirations.persistent()).contains(key1, key2);
}).verifyComplete();
}
@ParameterizedRedisTest // DATAREDIS-602

View File

@@ -15,8 +15,9 @@
*/
package org.springframework.data.redis.support.collections;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.*;
import static org.assertj.core.api.Assumptions.*;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assumptions.assumeThat;
import java.io.IOException;
import java.text.DecimalFormat;
@@ -35,7 +36,6 @@ import java.util.concurrent.TimeUnit;
import org.assertj.core.api.Assumptions;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.redis.DoubleAsStringObjectFactory;
import org.springframework.data.redis.LongAsStringObjectFactory;
@@ -197,7 +197,7 @@ public abstract class AbstractRedisMapIntegrationTests<K, V> {
assertThat(map.increment(k1, 10)).isEqualTo(Long.valueOf(Long.valueOf((String) v1) + 10));
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testExpire() {
@@ -216,7 +216,7 @@ public abstract class AbstractRedisMapIntegrationTests<K, V> {
assertThat(ops.persist()).satisfies(ExpireChanges::allOk);
}
@ParameterizedRedisTest
@ParameterizedRedisTest // GH-3054
@EnabledOnCommand("HEXPIRE")
void testExpireAt() {