Skip to content

Commit

Permalink
Java: Add expire, expireAt, pexpire, pexpireAt and ttl comm…
Browse files Browse the repository at this point in the history
…ands. (valkey-io#1033)

* Java: Add `expire`, `expireAt`, `pexpire`, `pexpireAt` and `ttl` commands
---------

Signed-off-by: Andrew Carbonetto <andrew.carbonetto@improving.com>
Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com>
Co-authored-by: SanHalacogluImproving <san.halacoglu@improving.com>
Co-authored-by: Yury-Fridlyand <yury.fridlyand@improving.com>

* Updated based on PR comments.

* Spotless and fixed ordering in TransactionTests.

---------

Signed-off-by: Andrew Carbonetto <andrew.carbonetto@improving.com>
Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com>
Co-authored-by: Andrew Carbonetto <andrew.carbonetto@improving.com>
Co-authored-by: Yury-Fridlyand <yury.fridlyand@improving.com>
  • Loading branch information
3 people authored and cyip10 committed Jun 24, 2024
1 parent 273f07c commit 958283d
Show file tree
Hide file tree
Showing 7 changed files with 965 additions and 8 deletions.
70 changes: 70 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import static redis_request.RedisRequestOuterClass.RequestType.DecrBy;
import static redis_request.RedisRequestOuterClass.RequestType.Del;
import static redis_request.RedisRequestOuterClass.RequestType.Exists;
import static redis_request.RedisRequestOuterClass.RequestType.Expire;
import static redis_request.RedisRequestOuterClass.RequestType.ExpireAt;
import static redis_request.RedisRequestOuterClass.RequestType.GetString;
import static redis_request.RedisRequestOuterClass.RequestType.HashDel;
import static redis_request.RedisRequestOuterClass.RequestType.HashExists;
Expand All @@ -24,20 +26,24 @@
import static redis_request.RedisRequestOuterClass.RequestType.LPush;
import static redis_request.RedisRequestOuterClass.RequestType.MGet;
import static redis_request.RedisRequestOuterClass.RequestType.MSet;
import static redis_request.RedisRequestOuterClass.RequestType.PExpire;
import static redis_request.RedisRequestOuterClass.RequestType.PExpireAt;
import static redis_request.RedisRequestOuterClass.RequestType.RPop;
import static redis_request.RedisRequestOuterClass.RequestType.RPush;
import static redis_request.RedisRequestOuterClass.RequestType.SAdd;
import static redis_request.RedisRequestOuterClass.RequestType.SCard;
import static redis_request.RedisRequestOuterClass.RequestType.SMembers;
import static redis_request.RedisRequestOuterClass.RequestType.SRem;
import static redis_request.RedisRequestOuterClass.RequestType.SetString;
import static redis_request.RedisRequestOuterClass.RequestType.TTL;
import static redis_request.RedisRequestOuterClass.RequestType.Unlink;

import glide.api.commands.GenericBaseCommands;
import glide.api.commands.HashCommands;
import glide.api.commands.ListBaseCommands;
import glide.api.commands.SetCommands;
import glide.api.commands.StringCommands;
import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.SetOptions;
import glide.api.models.configuration.BaseClientConfiguration;
import glide.api.models.exceptions.RedisException;
Expand Down Expand Up @@ -404,4 +410,68 @@ public CompletableFuture<Long> exists(@NonNull String[] keys) {
public CompletableFuture<Long> unlink(@NonNull String[] keys) {
return commandManager.submitNewCommand(Unlink, keys, this::handleLongResponse);
}

@Override
public CompletableFuture<Boolean> expire(@NonNull String key, long seconds) {
return commandManager.submitNewCommand(
Expire, new String[] {key, Long.toString(seconds)}, this::handleBooleanResponse);
}

@Override
public CompletableFuture<Boolean> expire(
@NonNull String key, long seconds, @NonNull ExpireOptions expireOptions) {
String[] arguments =
ArrayUtils.addAll(new String[] {key, Long.toString(seconds)}, expireOptions.toArgs());
return commandManager.submitNewCommand(Expire, arguments, this::handleBooleanResponse);
}

@Override
public CompletableFuture<Boolean> expireAt(@NonNull String key, long unixSeconds) {
return commandManager.submitNewCommand(
ExpireAt, new String[] {key, Long.toString(unixSeconds)}, this::handleBooleanResponse);
}

@Override
public CompletableFuture<Boolean> expireAt(
@NonNull String key, long unixSeconds, @NonNull ExpireOptions expireOptions) {
String[] arguments =
ArrayUtils.addAll(new String[] {key, Long.toString(unixSeconds)}, expireOptions.toArgs());
return commandManager.submitNewCommand(ExpireAt, arguments, this::handleBooleanResponse);
}

@Override
public CompletableFuture<Boolean> pexpire(@NonNull String key, long milliseconds) {
return commandManager.submitNewCommand(
PExpire, new String[] {key, Long.toString(milliseconds)}, this::handleBooleanResponse);
}

@Override
public CompletableFuture<Boolean> pexpire(
@NonNull String key, long milliseconds, @NonNull ExpireOptions expireOptions) {
String[] arguments =
ArrayUtils.addAll(new String[] {key, Long.toString(milliseconds)}, expireOptions.toArgs());
return commandManager.submitNewCommand(PExpire, arguments, this::handleBooleanResponse);
}

@Override
public CompletableFuture<Boolean> pexpireAt(@NonNull String key, long unixMilliseconds) {
return commandManager.submitNewCommand(
PExpireAt,
new String[] {key, Long.toString(unixMilliseconds)},
this::handleBooleanResponse);
}

@Override
public CompletableFuture<Boolean> pexpireAt(
@NonNull String key, long unixMilliseconds, @NonNull ExpireOptions expireOptions) {
String[] arguments =
ArrayUtils.addAll(
new String[] {key, Long.toString(unixMilliseconds)}, expireOptions.toArgs());
return commandManager.submitNewCommand(PExpireAt, arguments, this::handleBooleanResponse);
}

@Override
public CompletableFuture<Long> ttl(@NonNull String key) {
return commandManager.submitNewCommand(TTL, new String[] {key}, this::handleLongResponse);
}
}
214 changes: 212 additions & 2 deletions java/client/src/main/java/glide/api/commands/GenericBaseCommands.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api.commands;

import glide.api.models.commands.ExpireOptions;
import java.util.concurrent.CompletableFuture;

/**
* Generic Commands interface to handle generic commands for all server requests for both standalone
* and cluster clients.
* Generic Commands interface to handle generic commands for all server requests.
*
* @see <a href="https://redis.io/commands/?group=generic">Generic Commands</a>
*/
Expand Down Expand Up @@ -53,4 +53,214 @@ public interface GenericBaseCommands {
* </pre>
*/
CompletableFuture<Long> unlink(String[] keys);

/**
* Sets a timeout on <code>key</code> in seconds. After the timeout has expired, the <code>key
* </code> will automatically be deleted.<br>
* If <code>key</code> already has an existing <code>expire
* </code> set, the time to live is updated to the new value.<br>
* If <code>seconds</code> is a non-positive number, the <code>key</code> will be deleted rather
* than expired.<br>
* The timeout will only be cleared by commands that delete or overwrite the contents of <code>key
* </code>.
*
* @see <a href="https://redis.io/commands/expire/">redis.io</a> for details.
* @param key The key to set timeout on it.
* @param seconds The timeout in seconds.
* @return <code>true</code> if the timeout was set. <code>false</code> if the timeout was not
* set. e.g. <code>key</code> doesn't exist.
* @example
* <pre>
* Boolean isSet = client.expire("my_key", 60).get()
* assert isSet //Indicates that a timeout of 60 seconds has been set for "my_key."
* </pre>
*/
CompletableFuture<Boolean> expire(String key, long seconds);

/**
* Sets a timeout on <code>key</code> in seconds. After the timeout has expired, the <code>key
* </code> will automatically be deleted.<br>
* If <code>key</code> already has an existing <code>expire
* </code> set, the time to live is updated to the new value.<br>
* If <code>seconds</code> is a non-positive number, the <code>key</code> will be deleted rather
* than expired.<br>
* The timeout will only be cleared by commands that delete or overwrite the contents of <code>key
* </code>.
*
* @see <a href="https://redis.io/commands/expire/">redis.io</a> for details.
* @param key The key to set timeout on it.
* @param seconds The timeout in seconds.
* @param expireOptions The expire options.
* @return <code>true</code> if the timeout was set. <code>false</code> if the timeout was not
* set. e.g. <code>key</code> doesn't exist, or operation skipped due to the provided
* arguments.
* @example
* <pre>
* Boolean isSet = client.expire("my_key", 60, ExpireOptions.HAS_NO_EXPIRY).get()
* assert isSet //Indicates that a timeout of 60 seconds has been set for "my_key."
* </pre>
*/
CompletableFuture<Boolean> expire(String key, long seconds, ExpireOptions expireOptions);

/**
* Sets a timeout on <code>key</code>. It takes an absolute Unix timestamp (seconds since January
* 1, 1970) instead of specifying the number of seconds.<br>
* A timestamp in the past will delete the <code>key</code> immediately. After the timeout has
* expired, the <code>key</code> will automatically be deleted.<br>
* If <code>key</code> already has an existing <code>expire</code> set, the time to live is
* updated to the new value.<br>
* The timeout will only be cleared by commands that delete or overwrite the contents of <code>key
* </code>.
*
* @see <a href="https://redis.io/commands/expireat/">redis.io</a> for details.
* @param key The key to set timeout on it.
* @param unixSeconds The timeout in an absolute Unix timestamp.
* @return <code>true</code> if the timeout was set. <code>false</code> if the timeout was not
* set. e.g. <code>key</code> doesn't exist.
* @example
* <pre>
* Boolean isSet = client.expireAt("my_key", Instant.now().getEpochSecond() + 10).get()
* assert isSet
* </pre>
*/
CompletableFuture<Boolean> expireAt(String key, long unixSeconds);

/**
* Sets a timeout on <code>key</code>. It takes an absolute Unix timestamp (seconds since January
* 1, 1970) instead of specifying the number of seconds.<br>
* A timestamp in the past will delete the <code>key</code> immediately. After the timeout has
* expired, the <code>key</code> will automatically be deleted.<br>
* If <code>key</code> already has an existing <code>expire</code> set, the time to live is
* updated to the new value.<br>
* The timeout will only be cleared by commands that delete or overwrite the contents of <code>key
* </code>.
*
* @see <a href="https://redis.io/commands/expireat/">redis.io</a> for details.
* @param key The key to set timeout on it.
* @param unixSeconds The timeout in an absolute Unix timestamp.
* @param expireOptions The expire options.
* @return <code>true</code> if the timeout was set. <code>false</code> if the timeout was not
* set. e.g. <code>key</code> doesn't exist, or operation skipped due to the provided
* arguments.
* @example
* <pre>
* Boolean isSet = client.expireAt("my_key", Instant.now().getEpochSecond() + 10, ExpireOptions.HasNoExpiry).get()
* assert isSet
* </pre>
*/
CompletableFuture<Boolean> expireAt(String key, long unixSeconds, ExpireOptions expireOptions);

/**
* Sets a timeout on <code>key</code> in milliseconds. After the timeout has expired, the <code>
* key</code> will automatically be deleted.<br>
* If <code>key</code> already has an existing <code>
* expire</code> set, the time to live is updated to the new value.<br>
* If <code>milliseconds</code> is a non-positive number, the <code>key</code> will be deleted
* rather than expired.<br>
* The timeout will only be cleared by commands that delete or overwrite the contents of <code>key
* </code>.
*
* @see <a href="https://redis.io/commands/pexpire/">redis.io</a> for details.
* @param key The key to set timeout on it.
* @param milliseconds The timeout in milliseconds.
* @return <code>true</code> if the timeout was set. <code>false</code> if the timeout was not
* set. e.g. <code>key</code> doesn't exist.
* @example
* <pre>
* Boolean isSet = client.pexpire("my_key", 60000).get()
* assert isSet
* </pre>
*/
CompletableFuture<Boolean> pexpire(String key, long milliseconds);

/**
* Sets a timeout on <code>key</code> in milliseconds. After the timeout has expired, the <code>
* key</code> will automatically be deleted.<br>
* If <code>key</code> already has an existing expire set, the time to live is updated to the new
* value.<br>
* If <code>milliseconds</code> is a non-positive number, the <code>key</code> will be deleted
* rather than expired.<br>
* The timeout will only be cleared by commands that delete or overwrite the contents of <code>key
* </code>.
*
* @see <a href="https://redis.io/commands/pexpire/">redis.io</a> for details.
* @param key The key to set timeout on it.
* @param milliseconds The timeout in milliseconds.
* @param expireOptions The expire options.
* @return <code>true</code> if the timeout was set. <code>false</code> if the timeout was not
* set. e.g. <code>key</code> doesn't exist, or operation skipped due to the provided
* arguments.
* @example
* <pre>
* Boolean isSet = client.pexpire("my_key", 60000, ExpireOptions.HasNoExpiry).get()
* assert isSet
* </pre>
*/
CompletableFuture<Boolean> pexpire(String key, long milliseconds, ExpireOptions expireOptions);

/**
* Sets a timeout on <code>key</code>. It takes an absolute Unix timestamp (milliseconds since
* January 1, 1970) instead of specifying the number of milliseconds.<br>
* A timestamp in the past will delete the <code>key</code> immediately. After the timeout has
* expired, the <code>key</code> will automatically be deleted.<br>
* If <code>key</code> already has an existing <code>expire</code> set, the time to live is
* updated to the new value.<br>
* The timeout will only be cleared by commands that delete or overwrite the contents of <code>key
* </code>.
*
* @see <a href="https://redis.io/commands/pexpireat/">redis.io</a> for details.
* @param key The <code>key</code> to set timeout on it.
* @param unixMilliseconds The timeout in an absolute Unix timestamp.
* @return <code>true</code> if the timeout was set. <code>false</code> if the timeout was not
* set. e.g. <code>key</code> doesn't exist.
* @example
* <pre>
* Boolean isSet = client.pexpireAt("my_key", Instant.now().toEpochMilli() + 10).get()
* assert isSet
* </pre>
*/
CompletableFuture<Boolean> pexpireAt(String key, long unixMilliseconds);

/**
* Sets a timeout on <code>key</code>. It takes an absolute Unix timestamp (milliseconds since
* January 1, 1970) instead of specifying the number of milliseconds.<br>
* A timestamp in the past will delete the <code>key</code> immediately. After the timeout has
* expired, the <code>key</code> will automatically be deleted.<br>
* If <code>key</code> already has an existing <code>expire</code> set, the time to live is
* updated to the new value.<br>
* The timeout will only be cleared by commands that delete or overwrite the contents of <code>key
* </code>.
*
* @see <a href="https://redis.io/commands/pexpireat/">redis.io</a> for details.
* @param key The <code>key</code> to set timeout on it.
* @param unixMilliseconds The timeout in an absolute Unix timestamp.
* @param expireOptions The expire option.
* @return <code>true</code> if the timeout was set. <code>false</code> if the timeout was not
* set. e.g. <code>key</code> doesn't exist, or operation skipped due to the provided
* arguments.
* @example
* <pre>
* Boolean isSet = client.pexpireAt("my_key", Instant.now().toEpochMilli() + 10, ExpireOptions.HasNoExpiry).get()
* assert isSet
* </pre>
*/
CompletableFuture<Boolean> pexpireAt(
String key, long unixMilliseconds, ExpireOptions expireOptions);

/**
* Returns the remaining time to live of <code>key</code> that has a timeout.
*
* @see <a href="https://redis.io/commands/ttl/">redis.io</a> for details.
* @param key The <code>key</code> to return its timeout.
* @return TTL in seconds, <code>-2</code> if <code>key</code> does not exist, or <code>-1</code>
* if <code>key</code> exists but has no associated expire.
* @example
* <pre>
* Long timeRemaining = client.ttl("my_key").get()
* assert timeRemaining == 3600L //Indicates that "my_key" has a remaining time to live of 3600 seconds.
* Long timeRemaining = client.ttl("nonexistent_key").get()
* assert timeRemaining == -2L //Returns -2 for a non-existing key.
* </pre>
*/
CompletableFuture<Long> ttl(String key);
}
Loading

0 comments on commit 958283d

Please sign in to comment.