Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java: Add HSTRLEN command. #1463

Merged
merged 4 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -188,6 +188,7 @@ enum RequestType {
ZInter = 146;
BitPos = 147;
BitOp = 148;
HStrlen = 149;
FunctionLoad = 150;
LMPop = 155;
}
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 @@ -158,6 +158,7 @@ pub enum RequestType {
ZInter = 146,
BitPos = 147,
BitOp = 148,
HStrlen = 149,
FunctionLoad = 150,
LMPop = 155,
}
Expand Down Expand Up @@ -323,6 +324,7 @@ impl From<::protobuf::EnumOrUnknown<ProtobufRequestType>> for RequestType {
ProtobufRequestType::FunctionLoad => RequestType::FunctionLoad,
acarbonetto marked this conversation as resolved.
Show resolved Hide resolved
ProtobufRequestType::BitPos => RequestType::BitPos,
ProtobufRequestType::BitOp => RequestType::BitOp,
ProtobufRequestType::HStrlen => RequestType::HStrlen,
}
}
}
Expand Down Expand Up @@ -482,6 +484,7 @@ impl RequestType {
RequestType::FunctionLoad => Some(get_two_word_command("FUNCTION", "LOAD")),
acarbonetto marked this conversation as resolved.
Show resolved Hide resolved
RequestType::BitPos => Some(cmd("BITPOS")),
RequestType::BitOp => Some(cmd("BITOP")),
RequestType::HStrlen => Some(cmd("HSTRLEN")),
}
}
}
7 changes: 7 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.HRandField;
import static redis_request.RedisRequestOuterClass.RequestType.HSet;
import static redis_request.RedisRequestOuterClass.RequestType.HSetNX;
import static redis_request.RedisRequestOuterClass.RequestType.HStrlen;
import static redis_request.RedisRequestOuterClass.RequestType.HVals;
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
Expand Down Expand Up @@ -555,6 +556,12 @@ public CompletableFuture<String[]> hkeys(@NonNull String key) {
response -> castArray(handleArrayResponse(response), String.class));
}

@Override
public CompletableFuture<Long> hstrlen(@NonNull String key, @NonNull String field) {
return commandManager.submitNewCommand(
HStrlen, new String[] {key, field}, this::handleLongResponse);
}

@Override
public CompletableFuture<String> hrandfield(@NonNull String key) {
return commandManager.submitNewCommand(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ public interface HashBaseCommands {
/**
* Returns all field names in the hash stored at <code>key</code>.
*
* @see <a href="https://valkey.io/commands/hkeys/">redis.io</a> for details
* @see <a href="https://valkey.io/commands/hkeys/">valkey.io</a> for details.
* @param key The key of the hash.
* @return An <code>array</code> of field names in the hash, or an <code>empty array</code> when
* the key does not exist.
Expand All @@ -237,6 +237,23 @@ public interface HashBaseCommands {
*/
CompletableFuture<String[]> hkeys(String key);

/**
* Returns the string length of the value associated with <code>field</code> in the hash stored at
* <code>key</code>.
*
* @see <a href="https://valkey.io/commands/hstrlen/">valkey.io</a> for details.
* @param key The key of the hash.
* @param field The field in the hash.
* @return The string length or <code>0</code> if <code>field</code> or <code>key</code> does not
* exist.
* @example
* <pre>{@code
* Long strlen = client.hstrlen("my_hash", "my_field").get();
* assert strlen >= 0L;
* }</pre>
*/
CompletableFuture<Long> hstrlen(String key, String field);

/**
* Returns a random field name from the hash value stored at <code>key</code>.
*
Expand Down
16 changes: 16 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 @@ -57,6 +57,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.HRandField;
import static redis_request.RedisRequestOuterClass.RequestType.HSet;
import static redis_request.RedisRequestOuterClass.RequestType.HSetNX;
import static redis_request.RedisRequestOuterClass.RequestType.HStrlen;
import static redis_request.RedisRequestOuterClass.RequestType.HVals;
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
Expand Down Expand Up @@ -715,6 +716,21 @@ public T hkeys(@NonNull String key) {
return getThis();
}

/**
* Returns the string length of the value associated with <code>field</code> in the hash stored at
* <code>key</code>.
*
* @see <a href="https://valkey.io/commands/hstrlen/">valkey.io</a> for details.
* @param key The key of the hash.
* @param field The field in the hash.
* @return Command Response - The string length or <code>0</code> if <code>field</code> or <code>
* key</code> does not exist.
*/
public T hstrlen(@NonNull String key, @NonNull String field) {
protobufTransaction.addCommands(buildCommand(HStrlen, buildArgs(key, field)));
return getThis();
}

/**
* Returns a random field name from the hash value stored at <code>key</code>.
*
Expand Down
26 changes: 26 additions & 0 deletions java/client/src/test/java/glide/api/RedisClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.HRandField;
import static redis_request.RedisRequestOuterClass.RequestType.HSet;
import static redis_request.RedisRequestOuterClass.RequestType.HSetNX;
import static redis_request.RedisRequestOuterClass.RequestType.HStrlen;
import static redis_request.RedisRequestOuterClass.RequestType.HVals;
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
Expand Down Expand Up @@ -1429,6 +1430,31 @@ public void hkeys_returns_success() {
assertEquals(values, payload);
}

@SneakyThrows
@Test
public void hstrlen_returns_success() {
// setup
String key = "testKey";
String field = "field";
String[] args = {key, field};
Long value = 42L;

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

// match on protobuf request
when(commandManager.<Long>submitNewCommand(eq(HStrlen), eq(args), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<Long> response = service.hstrlen(key, field);
Long payload = response.get();

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

@SneakyThrows
@Test
public void hrandfield_returns_success() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.HRandField;
import static redis_request.RedisRequestOuterClass.RequestType.HSet;
import static redis_request.RedisRequestOuterClass.RequestType.HSetNX;
import static redis_request.RedisRequestOuterClass.RequestType.HStrlen;
import static redis_request.RedisRequestOuterClass.RequestType.HVals;
import static redis_request.RedisRequestOuterClass.RequestType.Incr;
import static redis_request.RedisRequestOuterClass.RequestType.IncrBy;
Expand Down Expand Up @@ -295,6 +296,9 @@ public void transaction_builds_protobuf_request(BaseTransaction<?> transaction)
transaction.hkeys("key");
results.add(Pair.of(HKeys, buildArgs("key")));

transaction.hstrlen("key", "field");
results.add(Pair.of(HStrlen, buildArgs("key", "field")));

transaction
.hrandfield("key")
.hrandfieldWithCount("key", 2)
Expand Down
25 changes: 24 additions & 1 deletion java/integTest/src/test/java/glide/SharedCommandTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -775,13 +775,36 @@ public void hkeys(BaseClient client) {

assertEquals(0, client.hkeys(key2).get().length);

// Key exists, but it is not a List
// Key exists, but it is not a hash
assertEquals(OK, client.set(key2, "value").get());
Exception executionException =
assertThrows(ExecutionException.class, () -> client.hkeys(key2).get());
assertTrue(executionException.getCause() instanceof RequestException);
}

@SneakyThrows
@ParameterizedTest(autoCloseArguments = false)
@MethodSource("getClients")
public void hstrlen(BaseClient client) {
String key1 = UUID.randomUUID().toString();
String key2 = UUID.randomUUID().toString();

assertEquals(1, client.hset(key1, Map.of("field", "value")).get());
assertEquals(5L, client.hstrlen(key1, "field").get());

// missing value
assertEquals(0, client.hstrlen(key1, "field 2").get());

// missing key
assertEquals(0, client.hstrlen(key2, "field").get());

// Key exists, but it is not a hash
assertEquals(OK, client.set(key2, "value").get());
Exception executionException =
assertThrows(ExecutionException.class, () -> client.hstrlen(key2, "field").get());
assertInstanceOf(RequestException.class, executionException.getCause());
}

@SneakyThrows
@ParameterizedTest(autoCloseArguments = false)
@MethodSource("getClients")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@ private static Object[] hashCommands(BaseTransaction<?> transaction) {
.hrandfieldWithCountWithValues(hashKey1, -2)
.hincrBy(hashKey1, field3, 5)
.hincrByFloat(hashKey1, field3, 5.5)
.hkeys(hashKey1);
.hkeys(hashKey1)
.hstrlen(hashKey1, field2);

return new Object[] {
2L, // hset(hashKey1, Map.of(field1, value1, field2, value2))
Expand All @@ -236,6 +237,7 @@ private static Object[] hashCommands(BaseTransaction<?> transaction) {
5L, // hincrBy(hashKey1, field3, 5)
10.5, // hincrByFloat(hashKey1, field3, 5.5)
new String[] {field2, field3}, // hkeys(hashKey1)
(long) value2.length(), // hstrlen(hashKey1, field2)
};
}

Expand Down
Loading