Skip to content

Commit

Permalink
Implement HEXPIRE, HEXPIREAT, HEXPIRETIME and HPERSIST (redis#2836)
Browse files Browse the repository at this point in the history
* HEXPIRE implemented with integration tests

* Polishing to integration test, added unit test

* Move new commands to RedisHashCommands, added HEXPIREAT, HEXPIRETIME and HPERSIST

* Make sure we reset the configuration setting after the new hash commands were tested

* Broke one test because of wrong configuration setting; the other is unstable, trying to fix it

* Polishing imports

* Polishin : Copyright change not needed
  • Loading branch information
tishun authored and thachlp committed Jun 22, 2024
1 parent 430945e commit c1d213c
Show file tree
Hide file tree
Showing 15 changed files with 1,539 additions and 86 deletions.
86 changes: 77 additions & 9 deletions src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,6 @@
*/
package io.lettuce.core;

import static io.lettuce.core.protocol.CommandType.*;

import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.lettuce.core.GeoArgs.Unit;
import io.lettuce.core.api.StatefulConnection;
import io.lettuce.core.api.async.*;
Expand All @@ -50,6 +41,19 @@
import io.lettuce.core.protocol.ProtocolKeyword;
import io.lettuce.core.protocol.RedisCommand;

import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static io.lettuce.core.protocol.CommandType.EXEC;
import static io.lettuce.core.protocol.CommandType.GEORADIUS;
import static io.lettuce.core.protocol.CommandType.GEORADIUSBYMEMBER;
import static io.lettuce.core.protocol.CommandType.GEORADIUSBYMEMBER_RO;
import static io.lettuce.core.protocol.CommandType.GEORADIUS_RO;

/**
* An asynchronous and thread-safe API for a Redis connection.
*
Expand Down Expand Up @@ -794,6 +798,27 @@ public RedisFuture<Boolean> expire(K key, Duration seconds, ExpireArgs expireArg
return expire(key, seconds.toMillis() / 1000, expireArgs);
}

@Override
public RedisFuture<Boolean> hexpire(K key, long seconds, K... fields) {
return hexpire(key, seconds, null, fields);
}

@Override
public RedisFuture<Boolean> hexpire(K key, long seconds, ExpireArgs expireArgs, K... fields) {
return dispatch(commandBuilder.hexpire(key, seconds, expireArgs, fields));
}

@Override
public RedisFuture<Boolean> hexpire(K key, Duration seconds, K... fields) {
return hexpire(key, seconds, null, fields);
}

@Override
public RedisFuture<Boolean> hexpire(K key, Duration seconds, ExpireArgs expireArgs, K... fields) {
LettuceAssert.notNull(seconds, "Timeout must not be null");
return hexpire(key, seconds.toMillis() / 1000, expireArgs, fields);
}

@Override
public RedisFuture<Boolean> expireat(K key, long timestamp) {
return expireat(key, timestamp, null);
Expand Down Expand Up @@ -826,11 +851,49 @@ public RedisFuture<Boolean> expireat(K key, Instant timestamp, ExpireArgs expire
return expireat(key, timestamp.toEpochMilli() / 1000, expireArgs);
}

@Override
public RedisFuture<Boolean> hexpireat(K key, long timestamp, K... fields) {
return hexpireat(key, timestamp, null, fields);
}

@Override
public RedisFuture<Boolean> hexpireat(K key, long timestamp, ExpireArgs expireArgs, K... fields) {
return dispatch(commandBuilder.hexpireat(key, timestamp, expireArgs, fields));

}

@Override
public RedisFuture<Boolean> hexpireat(K key, Date timestamp, K... fields) {
return hexpireat(key, timestamp, null, fields);
}

@Override
public RedisFuture<Boolean> hexpireat(K key, Date timestamp, ExpireArgs expireArgs, K... fields) {
LettuceAssert.notNull(timestamp, "Timestamp must not be null");
return hexpireat(key, timestamp.getTime() / 1000, expireArgs, fields);
}

@Override
public RedisFuture<Boolean> hexpireat(K key, Instant timestamp, K... fields) {
return hexpireat(key, timestamp, null, fields);
}

@Override
public RedisFuture<Boolean> hexpireat(K key, Instant timestamp, ExpireArgs expireArgs, K... fields) {
LettuceAssert.notNull(timestamp, "Timestamp must not be null");
return hexpireat(key, timestamp.toEpochMilli() / 1000, expireArgs, fields);
}

@Override
public RedisFuture<Long> expiretime(K key) {
return dispatch(commandBuilder.expiretime(key));
}

@Override
public RedisFuture<Long> hexpiretime(K key, K... fields) {
return dispatch(commandBuilder.hexpiretime(key, fields));
}

@Override
public <T> RedisFuture<T> fcall(String function, ScriptOutputType type, K... keys) {
return dispatch(commandBuilder.fcall(function, type, false, keys));
Expand Down Expand Up @@ -1489,6 +1552,11 @@ public RedisFuture<Boolean> persist(K key) {
return dispatch(commandBuilder.persist(key));
}

@Override
public RedisFuture<Boolean> hpersist(K key, K... fields) {
return dispatch(commandBuilder.hpersist(key, fields));
}

@Override
public RedisFuture<Boolean> pexpire(K key, long milliseconds) {
return pexpire(key, milliseconds, null);
Expand Down
87 changes: 77 additions & 10 deletions src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,6 @@
*/
package io.lettuce.core;

import static io.lettuce.core.protocol.CommandType.*;

import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;

import io.lettuce.core.GeoArgs.Unit;
import io.lettuce.core.api.StatefulConnection;
import io.lettuce.core.api.reactive.*;
Expand Down Expand Up @@ -59,6 +49,20 @@
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;

import static io.lettuce.core.protocol.CommandType.EXEC;
import static io.lettuce.core.protocol.CommandType.GEORADIUS;
import static io.lettuce.core.protocol.CommandType.GEORADIUSBYMEMBER;
import static io.lettuce.core.protocol.CommandType.GEORADIUSBYMEMBER_RO;
import static io.lettuce.core.protocol.CommandType.GEORADIUS_RO;

/**
* A reactive and thread-safe API for a Redis connection.
*
Expand Down Expand Up @@ -854,6 +858,27 @@ public Mono<Boolean> expire(K key, Duration seconds, ExpireArgs expireArgs) {
return expire(key, seconds.toMillis() / 1000, expireArgs);
}

@Override
public Mono<Boolean> hexpire(K key, long seconds, K... fields) {
return hexpire(key, seconds, null, fields);
}

@Override
public Mono<Boolean> hexpire(K key, long seconds, ExpireArgs expireArgs, K... fields) {
return createMono(() -> commandBuilder.hexpire(key, seconds, expireArgs, fields));
}

@Override
public Mono<Boolean> hexpire(K key, Duration seconds, K... fields) {
return hexpire(key, seconds, null, fields);
}

@Override
public Mono<Boolean> hexpire(K key, Duration seconds, ExpireArgs expireArgs, K... fields) {
LettuceAssert.notNull(seconds, "Timeout must not be null");
return hexpire(key, seconds.toMillis() / 1000, expireArgs, fields);
}

@Override
public Mono<Boolean> expireat(K key, long timestamp) {
return expireat(key, timestamp, null);
Expand Down Expand Up @@ -886,11 +911,48 @@ public Mono<Boolean> expireat(K key, Instant timestamp, ExpireArgs expireArgs) {
return expireat(key, timestamp.toEpochMilli() / 1000, expireArgs);
}

@Override
public Mono<Boolean> hexpireat(K key, long timestamp, K... fields) {
return hexpireat(key, timestamp, null, fields);
}

@Override
public Mono<Boolean> hexpireat(K key, long timestamp, ExpireArgs expireArgs, K... fields) {
return createMono(() -> commandBuilder.hexpireat(key, timestamp, expireArgs, fields));
}

@Override
public Mono<Boolean> hexpireat(K key, Date timestamp, K... fields) {
return hexpireat(key, timestamp, null, fields);
}

@Override
public Mono<Boolean> hexpireat(K key, Date timestamp, ExpireArgs expireArgs, K... fields) {
LettuceAssert.notNull(timestamp, "Timestamp must not be null");
return hexpireat(key, timestamp.getTime() / 1000, expireArgs, fields);
}

@Override
public Mono<Boolean> hexpireat(K key, Instant timestamp, K... fields) {
return hexpireat(key, timestamp, null, fields);
}

@Override
public Mono<Boolean> hexpireat(K key, Instant timestamp, ExpireArgs expireArgs, K... fields) {
LettuceAssert.notNull(timestamp, "Timestamp must not be null");
return hexpireat(key, timestamp.toEpochMilli() / 1000, expireArgs, fields);
}

@Override
public Mono<Long> expiretime(K key) {
return createMono(() -> commandBuilder.expiretime(key));
}

@Override
public Mono<Long> hexpiretime(K key, K... fields) {
return createMono(() -> commandBuilder.hexpiretime(key, fields));
}

@Override
public <T> Flux<T> fcall(String function, ScriptOutputType type, K... keys) {
return createFlux(() -> commandBuilder.fcall(function, type, false, keys));
Expand Down Expand Up @@ -1556,6 +1618,11 @@ public Mono<Boolean> persist(K key) {
return createMono(() -> commandBuilder.persist(key));
}

@Override
public Mono<Boolean> hpersist(K key, K... fields) {
return createMono(() -> commandBuilder.hpersist(key, fields));
}

@Override
public Mono<Boolean> pexpire(K key, long milliseconds) {
return pexpire(key, milliseconds, null);
Expand Down
77 changes: 64 additions & 13 deletions src/main/java/io/lettuce/core/RedisCommandBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,6 @@
*/
package io.lettuce.core;

import static io.lettuce.core.internal.LettuceStrings.*;
import static io.lettuce.core.protocol.CommandKeyword.*;
import static io.lettuce.core.protocol.CommandType.*;
import static io.lettuce.core.protocol.CommandType.COPY;
import static io.lettuce.core.protocol.CommandType.SAVE;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.lettuce.core.Range.Boundary;
import io.lettuce.core.XReadArgs.StreamOffset;
import io.lettuce.core.codec.RedisCodec;
Expand All @@ -48,6 +35,19 @@
import io.lettuce.core.protocol.CommandType;
import io.lettuce.core.protocol.RedisCommand;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static io.lettuce.core.internal.LettuceStrings.string;
import static io.lettuce.core.protocol.CommandKeyword.*;
import static io.lettuce.core.protocol.CommandType.*;
import static io.lettuce.core.protocol.CommandType.COPY;
import static io.lettuce.core.protocol.CommandType.SAVE;

/**
* @param <K>
* @param <V>
Expand Down Expand Up @@ -978,6 +978,38 @@ Command<K, V, Boolean> expire(K key, long seconds, ExpireArgs expireArgs) {
return createCommand(EXPIRE, new BooleanOutput<>(codec), args);
}

Command<K, V, Boolean> hexpire(K key, long seconds, ExpireArgs expireArgs, K... fields) {
notNullKey(key);
notEmpty(fields);

CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key).add(seconds);

if (expireArgs != null) {
expireArgs.build(args);
}

args.add(fields.length);
args.addKeys(fields);

return createCommand(HEXPIRE, new BooleanOutput<>(codec), args);
}

Command<K, V, Boolean> hexpireat(K key, long seconds, ExpireArgs expireArgs, K... fields) {
notNullKey(key);
notEmpty(fields);

CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key).add(seconds);

if (expireArgs != null) {
expireArgs.build(args);
}

args.add(fields.length);
args.addKeys(fields);

return createCommand(HEXPIREAT, new BooleanOutput<>(codec), args);
}

Command<K, V, Boolean> expireat(K key, long timestamp, ExpireArgs expireArgs) {
notNullKey(key);

Expand All @@ -997,6 +1029,15 @@ Command<K, V, Long> expiretime(K key) {
return createCommand(EXPIRETIME, new IntegerOutput<>(codec), args);
}

Command<K, V, Long> hexpiretime(K key, K... fields) {
notNullKey(key);

CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);
args.add(fields.length);
args.addKeys(fields);
return createCommand(HEXPIRETIME, new IntegerOutput<>(codec), args);
}

Command<K, V, String> flushall() {
return createCommand(FLUSHALL, new StatusOutput<>(codec));
}
Expand Down Expand Up @@ -2043,6 +2084,16 @@ Command<K, V, Boolean> persist(K key) {
return createCommand(PERSIST, new BooleanOutput<>(codec), key);
}

Command<K, V, Boolean> hpersist(K key, K... fields) {
notNullKey(key);

CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);
args.add(fields.length);
args.addKeys(fields);

return createCommand(HPERSIST, new BooleanOutput<>(codec), args);
}

Command<K, V, Boolean> pexpire(K key, long milliseconds, ExpireArgs expireArgs) {
notNullKey(key);

Expand Down
Loading

0 comments on commit c1d213c

Please sign in to comment.