Skip to content

Commit

Permalink
Merge pull request #374 from Bit-Quill/java/dev_cyip10_getex
Browse files Browse the repository at this point in the history
Java: implement GETEX
  • Loading branch information
cyip10 authored Jun 19, 2024
2 parents 4571c8a + b99fd2b commit de61e78
Show file tree
Hide file tree
Showing 10 changed files with 310 additions and 0 deletions.
1 change: 1 addition & 0 deletions glide-core/src/protobuf/redis_request.proto
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ enum RequestType {
LPos = 180;
LCS = 181;
GeoSearch = 182;
GetEx = 183;
}

message Command {
Expand Down
3 changes: 3 additions & 0 deletions glide-core/src/request_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ pub enum RequestType {
LPos = 180,
LCS = 181,
GeoSearch = 182,
GetEx = 183,
}

fn get_two_word_command(first: &str, second: &str) -> Cmd {
Expand Down Expand Up @@ -383,6 +384,7 @@ impl From<::protobuf::EnumOrUnknown<ProtobufRequestType>> for RequestType {
ProtobufRequestType::LPos => RequestType::LPos,
ProtobufRequestType::LCS => RequestType::LCS,
ProtobufRequestType::GeoSearch => RequestType::GeoSearch,
ProtobufRequestType::GetEx => RequestType::GetEx,
}
}
}
Expand Down Expand Up @@ -572,6 +574,7 @@ impl RequestType {
RequestType::LPos => Some(cmd("LPOS")),
RequestType::LCS => Some(cmd("LCS")),
RequestType::GeoSearch => Some(cmd("GEOSEARCH")),
RequestType::GetEx => Some(cmd("GETEX")),
}
}
}
14 changes: 14 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.Get;
import static redis_request.RedisRequestOuterClass.RequestType.GetBit;
import static redis_request.RedisRequestOuterClass.RequestType.GetDel;
import static redis_request.RedisRequestOuterClass.RequestType.GetEx;
import static redis_request.RedisRequestOuterClass.RequestType.GetRange;
import static redis_request.RedisRequestOuterClass.RequestType.HDel;
import static redis_request.RedisRequestOuterClass.RequestType.HExists;
Expand Down Expand Up @@ -165,6 +166,7 @@
import glide.api.commands.StringBaseCommands;
import glide.api.models.Script;
import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.GetExOptions;
import glide.api.models.commands.LInsertOptions.InsertPosition;
import glide.api.models.commands.LPosOptions;
import glide.api.models.commands.ListDirection;
Expand Down Expand Up @@ -476,6 +478,18 @@ public CompletableFuture<String> getdel(@NonNull String key) {
GetDel, new String[] {key}, this::handleStringOrNullResponse);
}

@Override
public CompletableFuture<String> getex(@NonNull String key) {
return commandManager.submitNewCommand(
GetEx, new String[] {key}, this::handleStringOrNullResponse);
}

@Override
public CompletableFuture<String> getex(@NonNull String key, @NonNull GetExOptions options) {
String[] arguments = ArrayUtils.addAll(new String[] {key}, options.toArgs());
return commandManager.submitNewCommand(GetEx, arguments, this::handleStringOrNullResponse);
}

@Override
public CompletableFuture<String> set(@NonNull byte[] key, @NonNull byte[] value) {
return commandManager.submitNewCommand(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api.commands;

import glide.api.models.commands.GetExOptions;
import glide.api.models.commands.SetOptions;
import glide.api.models.commands.SetOptions.ConditionalSet;
import glide.api.models.commands.SetOptions.SetOptionsBuilder;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import lombok.NonNull;

/**
* Supports commands and transactions for the "String Commands" group for standalone and cluster
Expand Down Expand Up @@ -74,6 +76,41 @@ public interface StringBaseCommands {
*/
CompletableFuture<String> getdel(String key);

/**
* Gets the value associated with the given <code>key</code>.
*
* @since Redis 6.2.0.
* @see <a href="https://redis.io/docs/latest/commands/getex/">redis.io</a> for details.
* @param key The <code>key</code> to retrieve from the database.
* @return If <code>key</code> exists, return the <code>value</code> of the <code>key</code>.
* Otherwise, return <code>null</code>.
* @example
* <pre>{@code
* String value = client.getex("key").get();
* assert value.equals("value");
* }</pre>
*/
CompletableFuture<String> getex(String key);

/**
* Gets the value associated with the given <code>key</code>.
*
* @since Redis 6.2.0.
* @see <a href="https://redis.io/docs/latest/commands/getex/">redis.io</a> for details.
* @param key The <code>key</code> to retrieve from the database.
* @param options The {@link GetExOptions} options.
* @return If <code>key</code> exists, return the <code>value</code> of the <code>key</code>.
* Otherwise, return <code>null</code>.
* @example
* <pre>{@code
* String response = client.set("key", "value").get();
* assert response.equals(OK);
* String value = client.getex("key", GetExOptions.Seconds(10L)).get();
* assert value.equals("value");
* }</pre>
*/
CompletableFuture<String> getex(String key, GetExOptions options);

/**
* Sets the given <code>key</code> with the given value.
*
Expand Down
33 changes: 33 additions & 0 deletions java/client/src/main/java/glide/api/models/BaseTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.Get;
import static redis_request.RedisRequestOuterClass.RequestType.GetBit;
import static redis_request.RedisRequestOuterClass.RequestType.GetDel;
import static redis_request.RedisRequestOuterClass.RequestType.GetEx;
import static redis_request.RedisRequestOuterClass.RequestType.GetRange;
import static redis_request.RedisRequestOuterClass.RequestType.HDel;
import static redis_request.RedisRequestOuterClass.RequestType.HExists;
Expand Down Expand Up @@ -182,6 +183,7 @@
import com.google.protobuf.ByteString;
import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.FlushMode;
import glide.api.models.commands.GetExOptions;
import glide.api.models.commands.InfoOptions;
import glide.api.models.commands.InfoOptions.Section;
import glide.api.models.commands.LInsertOptions.InsertPosition;
Expand Down Expand Up @@ -382,6 +384,37 @@ public T getdel(@NonNull String key) {
return getThis();
}

/**
* Gets the value associated with the given <code>key</code>.
*
* @since Redis 6.2.0.
* @see <a href="https://redis.io/docs/latest/commands/getex/">redis.io</a> for details.
* @param key The <code>key</code> to retrieve from the database.
* @return Command Response - If <code>key</code> exists, return the <code>value</code> of the
* <code>key</code>. Otherwise, return <code>null</code>.
*/
public T getex(@NonNull String key) {
ArgsArray commandArgs = buildArgs(key);
protobufTransaction.addCommands(buildCommand(GetEx, commandArgs));
return getThis();
}

/**
* Gets the value associated with the given <code>key</code>.
*
* @since Redis 6.2.0.
* @see <a href="https://redis.io/docs/latest/commands/getex/">redis.io</a> for details.
* @param key The <code>key</code> to retrieve from the database.
* @param options The {@link GetExOptions} options.
* @return Command Response - If <code>key</code> exists, return the <code>value</code> of the
* <code>key</code>. Otherwise, return <code>null</code>.
*/
public T getex(@NonNull String key, @NonNull GetExOptions options) {
ArgsArray commandArgs = buildArgs(ArrayUtils.addAll(new String[] {key}, options.toArgs()));
protobufTransaction.addCommands(buildCommand(GetEx, commandArgs));
return getThis();
}

/**
* Sets the given key with the given value.
*
Expand Down
111 changes: 111 additions & 0 deletions java/client/src/main/java/glide/api/models/commands/GetExOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api.models.commands;

import static glide.api.models.commands.GetExOptions.ExpiryType.MILLISECONDS;
import static glide.api.models.commands.GetExOptions.ExpiryType.PERSIST;
import static glide.api.models.commands.GetExOptions.ExpiryType.SECONDS;
import static glide.api.models.commands.GetExOptions.ExpiryType.UNIX_MILLISECONDS;
import static glide.api.models.commands.GetExOptions.ExpiryType.UNIX_SECONDS;

import glide.api.commands.StringBaseCommands;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;

/**
* Optional arguments to {@link StringBaseCommands#getex(String, GetExOptions)} command.
*
* @see <a href="https://redis.io/docs/latest/commands/getex/">redis.io</a>
*/
public class GetExOptions {

/** Expiry type for the time to live */
private final ExpiryType type;

/** The amount of time to live before the key expires. */
private Long count;

private GetExOptions(ExpiryType type) {
this.type = type;
}

private GetExOptions(ExpiryType type, Long count) {
this.type = type;
this.count = count;
}

/**
* Set the specified expire time, in seconds. Equivalent to <code>EX</code> in the Redis API.
*
* @param seconds The time to expire, in seconds.
* @return The options specifying the given expiry.
*/
public static GetExOptions Seconds(Long seconds) {
return new GetExOptions(SECONDS, seconds);
}

/**
* Set the specified expire time, in milliseconds. Equivalent to <code>PX</code> in the Redis API.
*
* @param milliseconds The time to expire, in milliseconds.
* @return The options specifying the given expiry.
*/
public static GetExOptions Milliseconds(Long milliseconds) {
return new GetExOptions(MILLISECONDS, milliseconds);
}

/**
* Set the specified Unix time at which the key will expire, in seconds. Equivalent to <code>
* EXAT</code> in the Redis API.
*
* @param unixSeconds The <code>UNIX TIME</code> to expire, in seconds.
* @return The options specifying the given expiry.
*/
public static GetExOptions UnixSeconds(Long unixSeconds) {
return new GetExOptions(UNIX_SECONDS, unixSeconds);
}

/**
* Set the specified Unix time at which the key will expire, in milliseconds. Equivalent to <code>
* PXAT</code> in the Redis API.
*
* @param unixMilliseconds The <code>UNIX TIME</code> to expire, in milliseconds.
* @return The options specifying the given expiry.
*/
public static GetExOptions UnixMilliseconds(Long unixMilliseconds) {
return new GetExOptions(UNIX_MILLISECONDS, unixMilliseconds);
}

/** Remove the time to live associated with the key. */
public static GetExOptions Persist() {
return new GetExOptions(PERSIST);
}

/** Types of value expiration configuration. */
@RequiredArgsConstructor
protected enum ExpiryType {
SECONDS("EX"),
MILLISECONDS("PX"),
UNIX_SECONDS("EXAT"),
UNIX_MILLISECONDS("PXAT"),
PERSIST("PERSIST");

private final String redisApi;
}

/**
* Converts GetExOptions into a String[] to pass to the <code>GETEX</code> command.
*
* @return String[]
*/
public String[] toArgs() {
List<String> optionArgs = new ArrayList<>();

optionArgs.add(type.redisApi);
if (count != null) {
optionArgs.add(String.valueOf(count));
}

return optionArgs.toArray(new String[0]);
}
}
45 changes: 45 additions & 0 deletions java/client/src/test/java/glide/api/RedisClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.Get;
import static redis_request.RedisRequestOuterClass.RequestType.GetBit;
import static redis_request.RedisRequestOuterClass.RequestType.GetDel;
import static redis_request.RedisRequestOuterClass.RequestType.GetEx;
import static redis_request.RedisRequestOuterClass.RequestType.GetRange;
import static redis_request.RedisRequestOuterClass.RequestType.HDel;
import static redis_request.RedisRequestOuterClass.RequestType.HExists;
Expand Down Expand Up @@ -218,6 +219,7 @@
import glide.api.models.commands.ConditionalChange;
import glide.api.models.commands.ExpireOptions;
import glide.api.models.commands.FlushMode;
import glide.api.models.commands.GetExOptions;
import glide.api.models.commands.InfoOptions;
import glide.api.models.commands.LPosOptions;
import glide.api.models.commands.ListDirection;
Expand Down Expand Up @@ -511,6 +513,49 @@ public void getdel() {
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void getex() {
// setup
String key = "testKey";
String value = "testValue";
CompletableFuture<String> testResponse = new CompletableFuture<>();
testResponse.complete(value);
when(commandManager.<String>submitNewCommand(eq(GetEx), eq(new String[] {key}), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<String> response = service.getex(key);
String payload = response.get();

// verify
assertEquals(testResponse, response);
assertEquals(value, payload);
}

@SneakyThrows
@Test
public void getex_options() {
// setup
GetExOptions options = GetExOptions.Seconds(10L);
String[] arguments = new String[] {"key", "EX", "10"};

CompletableFuture<String> testResponse = new CompletableFuture<>();
testResponse.complete("value");

// match on protobuf request
when(commandManager.<String>submitNewCommand(eq(GetEx), eq(arguments), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<String> response = service.getex("key", options);
String payload = response.get();

// verify
assertEquals(testResponse, response);
assertEquals("value", payload);
}

@SneakyThrows
@Test
public void set_returns_success() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.Get;
import static redis_request.RedisRequestOuterClass.RequestType.GetBit;
import static redis_request.RedisRequestOuterClass.RequestType.GetDel;
import static redis_request.RedisRequestOuterClass.RequestType.GetEx;
import static redis_request.RedisRequestOuterClass.RequestType.GetRange;
import static redis_request.RedisRequestOuterClass.RequestType.HDel;
import static redis_request.RedisRequestOuterClass.RequestType.HExists;
Expand Down Expand Up @@ -193,6 +194,7 @@

import com.google.protobuf.ByteString;
import glide.api.models.commands.ConditionalChange;
import glide.api.models.commands.GetExOptions;
import glide.api.models.commands.InfoOptions;
import glide.api.models.commands.LPosOptions;
import glide.api.models.commands.ListDirection;
Expand Down Expand Up @@ -254,6 +256,12 @@ public void transaction_builds_protobuf_request(BaseTransaction<?> transaction)
transaction.get("key");
results.add(Pair.of(Get, buildArgs("key")));

transaction.getex("key");
results.add(Pair.of(GetEx, buildArgs("key")));

transaction.getex("key", GetExOptions.Seconds(10L));
results.add(Pair.of(GetEx, buildArgs("key", "EX", "10")));

transaction.set("key", "value");
results.add(Pair.of(Set, buildArgs("key", "value")));

Expand Down
Loading

0 comments on commit de61e78

Please sign in to comment.