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 HSCAN command #1706

Merged
merged 39 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
29914cb
Java: Add `SSCAN` command (#394)
GumpacG Jun 28, 2024
51f3e35
Java: Add `ZSCAN` command (#397)
GumpacG Jun 29, 2024
878facc
WIP TODO: support transactions, docs, and more IT
GumpacG Jun 24, 2024
f028224
Added more tests
GumpacG Jun 25, 2024
79ce6fd
Added tests and javadocs
GumpacG Jun 27, 2024
9f76d08
Improved examples and tests
GumpacG Jun 27, 2024
0f69477
Correct use of SScanOptions instead of ScanOptions for SScan
jduo Jun 27, 2024
343c7ad
Remove plumbing for SCAN command
jduo Jun 27, 2024
851d952
Sleep after sadd() calls before sscan() calls
jduo Jun 28, 2024
c708547
Change sscan cursor to be a String
jduo Jun 28, 2024
450e17d
WIP with todos
GumpacG Jun 27, 2024
da923a4
Add ZScan to TransactionTestUtilities
jduo Jun 27, 2024
01c0794
Spotless cleanup
jduo Jun 27, 2024
ae014e5
Test fixes
jduo Jun 28, 2024
e65a9f7
Cleanup test code
jduo Jun 28, 2024
90cad59
Added better error info for set comparison failures
jduo Jun 28, 2024
213a873
More logging for test failures
jduo Jun 28, 2024
bb49b58
Add sleeps after zadd() calls
jduo Jun 28, 2024
e1bed7c
Longer sleeps
jduo Jun 28, 2024
3406cd8
Reduce wait time
jduo Jun 28, 2024
b908a0b
Experiment with unsigned 64-bit cursors
jduo Jun 28, 2024
7ba31b6
Fix rebase error
jduo Jun 28, 2024
cf86bfd
WIP TODO: support transactions, docs, and more IT
GumpacG Jun 24, 2024
1de0e9d
Added more tests
GumpacG Jun 25, 2024
43764ec
Added tests and javadocs
GumpacG Jun 27, 2024
fe4162f
Improved examples and tests
GumpacG Jun 27, 2024
2f73165
Sleep after sadd() calls before sscan() calls
jduo Jun 28, 2024
fc028cd
Change sscan cursor to be a String
jduo Jun 28, 2024
cdd69b0
Fix rebase conflicts
jduo Jun 29, 2024
a0f1158
Fix another rebase conflict
jduo Jun 29, 2024
e49be9f
Spotless
jduo Jun 29, 2024
3a0f696
HScan
jduo Jun 29, 2024
f410531
Flakey test
jduo Jun 29, 2024
c9ec010
Add HScan transaction unit test
jduo Jun 29, 2024
241ef45
Rename ScanOptions to BaseScanOptions
jduo Jun 29, 2024
fc2a4d1
Fix merge issues
jduo Jun 29, 2024
7eef0c1
Fix module-info ordering
jduo Jun 29, 2024
f1429ac
Tidy up docs
jduo Jun 29, 2024
b959c6c
PR comments
jduo Jun 29, 2024
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 @@ -240,6 +240,7 @@ enum RequestType {
XGroupSetId = 199;
SScan = 200;
ZScan = 201;
HScan = 202;
}

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 @@ -210,6 +210,7 @@ pub enum RequestType {
XGroupSetId = 199,
SScan = 200,
ZScan = 201,
HScan = 202,
}

fn get_two_word_command(first: &str, second: &str) -> Cmd {
Expand Down Expand Up @@ -423,6 +424,7 @@ impl From<::protobuf::EnumOrUnknown<ProtobufRequestType>> for RequestType {
ProtobufRequestType::XGroupSetId => RequestType::XGroupSetId,
ProtobufRequestType::SScan => RequestType::SScan,
ProtobufRequestType::ZScan => RequestType::ZScan,
ProtobufRequestType::HScan => RequestType::HScan,
}
}
}
Expand Down Expand Up @@ -634,6 +636,7 @@ impl RequestType {
RequestType::XGroupSetId => Some(get_two_word_command("XGROUP", "SETID")),
RequestType::SScan => Some(cmd("SSCAN")),
RequestType::ZScan => Some(cmd("ZSCAN")),
RequestType::HScan => Some(cmd("HSCAN")),
}
}
}
15 changes: 15 additions & 0 deletions java/client/src/main/java/glide/api/BaseClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.HLen;
import static redis_request.RedisRequestOuterClass.RequestType.HMGet;
import static redis_request.RedisRequestOuterClass.RequestType.HRandField;
import static redis_request.RedisRequestOuterClass.RequestType.HScan;
import static redis_request.RedisRequestOuterClass.RequestType.HSet;
import static redis_request.RedisRequestOuterClass.RequestType.HSetNX;
import static redis_request.RedisRequestOuterClass.RequestType.HStrlen;
Expand Down Expand Up @@ -215,6 +216,7 @@
import glide.api.models.commands.geospatial.GeoSearchStoreOptions;
import glide.api.models.commands.geospatial.GeoUnit;
import glide.api.models.commands.geospatial.GeospatialData;
import glide.api.models.commands.scan.HScanOptions;
import glide.api.models.commands.scan.SScanOptions;
import glide.api.models.commands.scan.ZScanOptions;
import glide.api.models.commands.stream.StreamAddOptions;
Expand Down Expand Up @@ -2935,4 +2937,17 @@ public CompletableFuture<Object[]> zscan(
String[] arguments = concatenateArrays(new String[] {key, cursor}, zScanOptions.toArgs());
return commandManager.submitNewCommand(ZScan, arguments, this::handleArrayResponse);
}

@Override
public CompletableFuture<Object[]> hscan(@NonNull String key, @NonNull String cursor) {
String[] arguments = new String[] {key, cursor};
return commandManager.submitNewCommand(HScan, arguments, this::handleArrayResponse);
}

@Override
public CompletableFuture<Object[]> hscan(
@NonNull String key, @NonNull String cursor, @NonNull HScanOptions hScanOptions) {
String[] arguments = concatenateArrays(new String[] {key, cursor}, hScanOptions.toArgs());
return commandManager.submitNewCommand(HScan, arguments, this::handleArrayResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package glide.api.commands;

import glide.api.models.GlideString;
import glide.api.models.commands.scan.HScanOptions;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

Expand Down Expand Up @@ -432,4 +433,75 @@ public interface HashBaseCommands {
* }</pre>
*/
CompletableFuture<String[][]> hrandfieldWithCountWithValues(String key, long count);

/**
* Iterates fields of Hash types and their associated values.
*
* @see <a href="https://valkey.io/commands/hscan">valkey.io</a> for details.
* @param key The key of the hash.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @return An <code>Array</code> of <code>Objects</code>. The first element is always the <code>
* cursor</code> for the next iteration of results. <code>"0"</code> will be the <code>cursor
* </code> returned on the last iteration of the result. The second element is always an
* <code>Array</code> of the subset of the hash held in <code>key</code>. The array in the
* second element is always a flattened series of <code>String</code> pairs, where the key is
* at even indices and the value is at odd indices.
* @example
* <pre>{@code
* // Assume key contains a set with 200 member-score pairs
* String cursor = "0";
* Object[] result;
* do {
* result = client.hscan(key1, cursor).get();
* cursor = result[0].toString();
* Object[] stringResults = (Object[]) result[1];
*
* System.out.println("\nHSCAN iteration:");
* for (int i = 0; i < stringResults.length; i += 2) {
* System.out.printf("{%s=%s}", stringResults[i], stringResults[i + 1]);
* if (i + 2 < stringResults.length) {
* System.out.print(", ");
* }
* }
* } while (!cursor.equals("0"));
* }</pre>
*/
CompletableFuture<Object[]> hscan(String key, String cursor);

/**
* Iterates fields of Hash types and their associated values.
*
* @see <a href="https://valkey.io/commands/hscan">valkey.io</a> for details.
* @param key The key of the hash.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @param hScanOptions The {@link HScanOptions}.
* @return An <code>Array</code> of <code>Objects</code>. The first element is always the <code>
* cursor</code> for the next iteration of results. <code>"0"</code> will be the <code>cursor
* </code> returned on the last iteration of the result. The second element is always an
* <code>Array</code> of the subset of the hash held in <code>key</code>. The array in the
* second element is always a flattened series of <code>String</code> pairs, where the key is
* at even indices and the value is at odd indices.
* @example
* <pre>{@code
* // Assume key contains a set with 200 member-score pairs
* String cursor = "0";
* Object[] result;
* do {
* result = client.hscan(key1, cursor, HScanOptions.builder().matchPattern("*").count(20L).build()).get();
* cursor = result[0].toString();
* Object[] stringResults = (Object[]) result[1];
*
* System.out.println("\nHSCAN iteration:");
* for (int i = 0; i < stringResults.length; i += 2) {
* System.out.printf("{%s=%s}", stringResults[i], stringResults[i + 1]);
* if (i + 2 < stringResults.length) {
* System.out.print(", ");
* }
* }
* } while (!cursor.equals("0"));
* }</pre>
*/
CompletableFuture<Object[]> hscan(String key, String cursor, HScanOptions hScanOptions);
}
Original file line number Diff line number Diff line change
Expand Up @@ -560,10 +560,10 @@ public interface SetBaseCommands {
*
* @see <a href="https://valkey.io/commands/sscan">valkey.io</a> for details.
* @param key The key of the set.
* @param cursor The cursor that points to the next iteration of results. A value of 0 indicates
* the start of the search.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @return An <code>Array</code> of <code>Objects</code>. The first element is always the <code>
* cursor</code> for the next iteration of results. <code>0</code> will be the <code>cursor
* cursor</code> for the next iteration of results. <code>"0"</code> will be the <code>cursor
* </code> returned on the last iteration of the set. The second element is always an <code>
* Array</code> of the subset of the set held in <code>key</code>.
* @example
Expand All @@ -588,11 +588,11 @@ public interface SetBaseCommands {
*
* @see <a href="https://valkey.io/commands/sscan">valkey.io</a> for details.
* @param key The key of the set.
* @param cursor The cursor that points to the next iteration of results. A value of 0 indicates
* the start of the search.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @param sScanOptions The {@link SScanOptions}.
* @return An <code>Array</code> of <code>Objects</code>. The first element is always the <code>
* cursor</code> for the next iteration of results. <code>0</code> will be the <code>cursor
* cursor</code> for the next iteration of results. <code>"0"</code> will be the <code>cursor
* </code> returned on the last iteration of the set. The second element is always an <code>
* Array</code> of the subset of the set held in <code>key</code>.
* @example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1584,10 +1584,10 @@ CompletableFuture<Map<String, Double>> zinterWithScores(
*
* @see <a href="https://valkey.io/commands/zscan">valkey.io</a> for details.
* @param key The key of the sorted set.
* @param cursor The cursor that points to the next iteration of results. A value of 0 indicates
* the start of the search.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @return An <code>Array</code> of <code>Objects</code>. The first element is always the <code>
* cursor</code> for the next iteration of results. <code>0</code> will be the <code>cursor
* cursor</code> for the next iteration of results. <code>"0"</code> will be the <code>cursor
* </code> returned on the last iteration of the sorted set. The second element is always an
* <code>
* Array</code> of the subset of the sorted set held in <code>key</code>. The array in the
Expand Down Expand Up @@ -1620,11 +1620,11 @@ CompletableFuture<Map<String, Double>> zinterWithScores(
*
* @see <a href="https://valkey.io/commands/zscan">valkey.io</a> for details.
* @param key The key of the sorted set.
* @param cursor The cursor that points to the next iteration of results. A value of 0 indicates
* the start of the search.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @param zScanOptions The {@link ZScanOptions}.
* @return An <code>Array</code> of <code>Objects</code>. The first element is always the <code>
* cursor</code> for the next iteration of results. <code>0</code> will be the <code>cursor
* cursor</code> for the next iteration of results. <code>"0"</code> will be the <code>cursor
* </code> returned on the last iteration of the sorted set. The second element is always an
* <code>
* Array</code> of the subset of the sorted set held in <code>key</code>. The array in the
Expand Down
67 changes: 55 additions & 12 deletions java/client/src/main/java/glide/api/models/BaseTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.HLen;
import static redis_request.RedisRequestOuterClass.RequestType.HMGet;
import static redis_request.RedisRequestOuterClass.RequestType.HRandField;
import static redis_request.RedisRequestOuterClass.RequestType.HScan;
import static redis_request.RedisRequestOuterClass.RequestType.HSet;
import static redis_request.RedisRequestOuterClass.RequestType.HSetNX;
import static redis_request.RedisRequestOuterClass.RequestType.HStrlen;
Expand Down Expand Up @@ -249,6 +250,7 @@
import glide.api.models.commands.geospatial.GeoSearchStoreOptions;
import glide.api.models.commands.geospatial.GeoUnit;
import glide.api.models.commands.geospatial.GeospatialData;
import glide.api.models.commands.scan.HScanOptions;
import glide.api.models.commands.scan.SScanOptions;
import glide.api.models.commands.scan.ZScanOptions;
import glide.api.models.commands.stream.StreamAddOptions;
Expand Down Expand Up @@ -5509,10 +5511,10 @@ public T geosearchstore(
*
* @see <a href="https://valkey.io/commands/sscan">valkey.io</a> for details.
* @param key The key of the set.
* @param cursor The cursor that points to the next iteration of results. A value of 0 indicates
* the start of the search.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @return Command Response - An <code>Array</code> of <code>Objects</code>. The first element is
* always the <code>cursor</code> for the next iteration of results. <code>0</code> will be
* always the <code>cursor</code> for the next iteration of results. <code>"0"</code> will be
* the <code>cursor</code> returned on the last iteration of the set. The second element is
* always an <code>Array</code> of the subset of the set held in <code>key</code>.
*/
Expand All @@ -5526,11 +5528,11 @@ public T sscan(@NonNull String key, @NonNull String cursor) {
*
* @see <a href="https://valkey.io/commands/sscan">valkey.io</a> for details.
* @param key The key of the set.
* @param cursor The cursor that points to the next iteration of results. A value of 0 indicates
* the start of the search.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @param sScanOptions The {@link SScanOptions}.
* @return Command Response - An <code>Array</code> of <code>Objects</code>. The first element is
* always the <code>cursor</code> for the next iteration of results. <code>0</code> will be
* always the <code>cursor</code> for the next iteration of results. <code>"0"</code> will be
* the <code>cursor</code> returned on the last iteration of the set. The second element is
* always an <code>Array</code> of the subset of the set held in <code>key</code>.
*/
Expand All @@ -5546,10 +5548,10 @@ public T sscan(@NonNull String key, @NonNull String cursor, @NonNull SScanOption
*
* @see <a href="https://valkey.io/commands/zscan">valkey.io</a> for details.
* @param key The key of the sorted set.
* @param cursor The cursor that points to the next iteration of results. A value of 0 indicates
* the start of the search.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @return Command Response - An <code>Array</code> of <code>Objects</code>. The first element is
* always the <code>cursor</code> for the next iteration of results. <code>0</code> will be
* always the <code>cursor</code> for the next iteration of results. <code>"0"</code> will be
* the <code>cursor</code> returned on the last iteration of the sorted set. The second
* element is always an <code>Array</code> of the subset of the sorted set held in <code>key
* </code>. The array in the second element is always a flattened series of <code>String
Expand All @@ -5565,11 +5567,11 @@ public T zscan(@NonNull String key, @NonNull String cursor) {
*
* @see <a href="https://valkey.io/commands/zscan">valkey.io</a> for details.
* @param key The key of the sorted set.
* @param cursor The cursor that points to the next iteration of results. A value of 0 indicates
* the start of the search.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @param zScanOptions The {@link ZScanOptions}.
* @return Command Response - An <code>Array</code> of <code>Objects</code>. The first element is
* always the <code>cursor</code> for the next iteration of results. <code>0</code> will be
* always the <code>cursor</code> for the next iteration of results. <code>"0"</code> will be
* the <code>cursor</code> returned on the last iteration of the sorted set. The second
* element is always an <code>Array</code> of the subset of the sorted set held in <code>key
* </code>. The array in the second element is always a flattened series of <code>String
Expand All @@ -5582,6 +5584,47 @@ public T zscan(@NonNull String key, @NonNull String cursor, @NonNull ZScanOption
return getThis();
}

/**
* Iterates fields of Hash types and their associated values.
*
* @see <a href="https://valkey.io/commands/hscan">valkey.io</a> for details.
* @param key The key of the hash.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @return Command Response - An <code>Array</code> of <code>Objects</code>. The first element is
* always the <code>cursor</code> for the next iteration of results. <code>"0"</code> will be
* the <code>cursor</code> returned on the last iteration of the result. The second element is
* always an <code>Array</code> of the subset of the hash held in <code>key</code>. The array
* in the second element is always a flattened series of <code>String</code> pairs, where the
* key is at even indices and the value is at odd indices.
*/
public T hscan(@NonNull String key, @NonNull String cursor) {
protobufTransaction.addCommands(buildCommand(HScan, buildArgs(key, cursor)));
return getThis();
}

/**
* Iterates fields of Hash types and their associated values.
*
* @see <a href="https://valkey.io/commands/hscan">valkey.io</a> for details.
* @param key The key of the hash.
* @param cursor The cursor that points to the next iteration of results. A value of <code>"0"
* </code> indicates the start of the search.
* @param hScanOptions The {@link HScanOptions}.
* @return Command Response - An <code>Array</code> of <code>Objects</code>. The first element is
* always the <code>cursor</code> for the next iteration of results. <code>"0"</code> will be
* the <code>cursor</code> returned on the last iteration of the result. The second element is
* always an <code>Array</code> of the subset of the hash held in <code>key</code>. The array
* in the second element is always a flattened series of <code>String</code> pairs, where the
* key is at even indices and the value is at odd indices.
*/
public T hscan(@NonNull String key, @NonNull String cursor, @NonNull HScanOptions hScanOptions) {
final ArgsArray commandArgs =
buildArgs(concatenateArrays(new String[] {key, cursor}, hScanOptions.toArgs()));
protobufTransaction.addCommands(buildCommand(HScan, commandArgs));
return getThis();
}

/** Build protobuf {@link Command} object for given command and arguments. */
protected Command buildCommand(RequestType requestType) {
return buildCommand(requestType, buildArgs());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api.models.commands.scan;

import glide.api.commands.HashBaseCommands;
import lombok.experimental.SuperBuilder;

/**
* Optional arguments for {@link HashBaseCommands#hscan(String, String, HScanOptions)}.
*
* @see <a href="https://valkey.io/commands/hscan/">valkey.io</a>
*/
@SuperBuilder
public class HScanOptions extends BaseScanOptions {}
2 changes: 1 addition & 1 deletion java/client/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
exports glide.api.models.commands.bitmap;
exports glide.api.models.commands.geospatial;
exports glide.api.models.commands.function;
exports glide.api.models.commands.scan;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

exports glide.api.models.commands.stream;
exports glide.api.models.configuration;
exports glide.api.models.exceptions;
exports glide.api.models.commands.scan;

requires com.google.protobuf;
requires io.netty.codec;
Expand Down
Loading
Loading