From a7bc16854722f13bfaaa679afc1f63ddfffaf1d4 Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Thu, 25 Jan 2024 15:25:07 -0800 Subject: [PATCH] Add ExamplesApp to test get/set/info/ping Signed-off-by: Andrew Carbonetto --- java/README.md | 27 +++--- .../clients/lettuce/LettuceAsyncClient.java | 2 +- java/examples/build.gradle | 23 +++++ .../main/java/glide/examples/ExamplesApp.java | 96 +++++++++++++++++++ .../glide/examples/clients/GlideClient.java | 27 ++++++ .../glide/examples/clients/JedisClient.java | 30 ++++++ .../examples/clients/LettuceAsyncClient.java | 45 +++++++++ java/settings.gradle | 1 + 8 files changed, 236 insertions(+), 15 deletions(-) create mode 100644 java/examples/build.gradle create mode 100644 java/examples/src/main/java/glide/examples/ExamplesApp.java create mode 100644 java/examples/src/main/java/glide/examples/clients/GlideClient.java create mode 100644 java/examples/src/main/java/glide/examples/clients/JedisClient.java create mode 100644 java/examples/src/main/java/glide/examples/clients/LettuceAsyncClient.java diff --git a/java/README.md b/java/README.md index a9379f32a1..97447f1057 100644 --- a/java/README.md +++ b/java/README.md @@ -9,8 +9,10 @@ to develop this Java wrapper. The Java client contains the following parts: -1. A Java client (lib folder): wrapper to rust client. -2. A benchmark app: A dedicated benchmarking tool designed to evaluate and compare the performance of GLIDE for Redis and other Java clients. +1. client: A Java-wrapper around the rust-core client. +2. examples: An examples app to test the client against a Redis localhost +3. benchmark: A dedicated benchmarking tool designed to evaluate and compare the performance of GLIDE for Redis and other Java clients. +4. IntegTest: An integration test sub-project for API and E2E testing ## Installation and Setup @@ -84,6 +86,7 @@ Other useful gradle developer commands: * `./gradlew :client:test` to run client unit tests * `./gradlew spotlessCheck` to check for codestyle issues * `./gradlew spotlessApply` to apply codestyle recommendations +* `./gradlew :examples:run` to run client examples * `./gradlew :benchmarks:run` to run performance benchmarks ## Basic Examples @@ -91,19 +94,15 @@ Other useful gradle developer commands: ### Standalone Redis: ```java -import glide.Client; -import glide.Client.SingleResponse; +import glide.api.RedisClient; -Client client = new Client(); +RedisClient client = RedisClient.CreateClient(); -SingleResponse connect = client.asyncConnectToRedis("localhost", 6379); -connect.await().isSuccess(); +CompletableFuture setResponse = client.set("key", "foobar"); +setResponse.get(); -SingleResponse set = client.asyncSet("key", "foobar"); -set.await().isSuccess(); - -SingleResponse get = client.asyncGet("key"); -get.await().getValue() == "foobar"; +CompletableFuture getResponse = client.get("key"); +getResponse.get() == "foobar"; ``` ### Benchmarks @@ -115,11 +114,11 @@ You can run benchmarks using `./gradlew run`. You can set arguments using the ar ./gradlew run --args="-resultsFile=output -dataSize \"100 1000\" -concurrentTasks \"10 100\" -clients all -host localhost -port 6279 -clientCount \"1 5\" -tls" ``` -The following arguments are accepted: +The following arguments are accepted: * `resultsFile`: the results output file * `concurrentTasks`: Number of concurrent tasks * `clients`: one of: all|jedis|lettuce|glide * `clientCount`: Client count * `host`: redis server host url * `port`: redis server port number -* `tls`: redis TLS configured +* `tls`: redis TLS configured \ No newline at end of file diff --git a/java/benchmarks/src/main/java/glide/benchmarks/clients/lettuce/LettuceAsyncClient.java b/java/benchmarks/src/main/java/glide/benchmarks/clients/lettuce/LettuceAsyncClient.java index fd581bb0ce..622b9d5443 100644 --- a/java/benchmarks/src/main/java/glide/benchmarks/clients/lettuce/LettuceAsyncClient.java +++ b/java/benchmarks/src/main/java/glide/benchmarks/clients/lettuce/LettuceAsyncClient.java @@ -29,7 +29,7 @@ public void connectToRedis(ConnectionSettings connectionSettings) { .withPort(connectionSettings.port) .withSsl(connectionSettings.useSsl) .build(); - if (connectionSettings.clusterMode) { + if (!connectionSettings.clusterMode) { client = RedisClient.create(uri); connection = ((RedisClient) client).connect(); asyncCommands = ((StatefulRedisConnection) connection).async(); diff --git a/java/examples/build.gradle b/java/examples/build.gradle new file mode 100644 index 0000000000..42d7b31858 --- /dev/null +++ b/java/examples/build.gradle @@ -0,0 +1,23 @@ +plugins { + // Apply the application plugin to add support for building a CLI application in Java. + id 'application' +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +dependencies { + implementation project(':client') + + implementation 'redis.clients:jedis:4.4.3' + implementation 'io.lettuce:lettuce-core:6.2.6.RELEASE' + implementation 'commons-cli:commons-cli:1.5.0' +} + +application { + // Define the main class for the application. + mainClass = 'glide.examples.ExamplesApp' + applicationDefaultJvmArgs = ['-Djava.library.path=../target/release'] +} diff --git a/java/examples/src/main/java/glide/examples/ExamplesApp.java b/java/examples/src/main/java/glide/examples/ExamplesApp.java new file mode 100644 index 0000000000..687414384a --- /dev/null +++ b/java/examples/src/main/java/glide/examples/ExamplesApp.java @@ -0,0 +1,96 @@ +package glide.examples; + +import glide.api.RedisClient; +import glide.examples.clients.GlideClient; +import glide.examples.clients.JedisClient; +import glide.examples.clients.LettuceAsyncClient; +import java.util.concurrent.ExecutionException; +import redis.clients.jedis.commands.JedisCommands; + +public class ExamplesApp { + + // main application entrypoint + public static void main(String[] args) { + + // runJedisExamples(); + // runLettuceExamples(); + runGlideExamples(); + } + + private static void runJedisExamples() { + ConnectionSettings settings = new ConnectionSettings("localhost", 6379, false, false); + + System.out.println("Connecting to Redis using Jedis-client"); + JedisCommands jedisCommands = JedisClient.connectToRedis(settings); + System.out.println("Jedis SET(myKey, myValue): " + jedisCommands.set("myKey", "myValue")); + System.out.println("Jedis GET(myKey): " + jedisCommands.get("myKey")); + System.out.println("Jedis GET(invalid): " + jedisCommands.get("invalid")); + } + + private static void runLettuceExamples() { + + ConnectionSettings settings = new ConnectionSettings("localhost", 6379, false, false); + + System.out.println("Connecting to Redis using Lettuce-client"); + LettuceAsyncClient lettuceAsyncClient = new LettuceAsyncClient(settings); + + try { + System.out.println( + "Lettuce SET(myKey, myValue): " + + lettuceAsyncClient.asyncCommands.set("myKey", "myValue").get()); + System.out.println( + "Lettuce GET(myKey): " + lettuceAsyncClient.asyncCommands.get("myKey").get()); + System.out.println( + "Lettuce GET(invalid): " + lettuceAsyncClient.asyncCommands.get("invalid").get()); + + } catch (InterruptedException | ExecutionException e) { + System.out.println("Lettuce example failed with an exception: "); + e.printStackTrace(); + } + } + + private static void runGlideExamples() { + ConnectionSettings settings = new ConnectionSettings("localhost", 6379, false, false); + + try { + RedisClient client = GlideClient.connectToGlide(settings); + + System.out.println("Glide PING: " + client.ping().get()); + System.out.println("Glide PING(custom): " + client.ping("found you!").get()); + + // panic + // System.out.println("Glide INFO(): " + client.info().get()); + + System.out.println("Glide SET(myKey, myValue): " + client.set("myKey", "myValue").get()); + System.out.println("Glide GET(myKey): " + client.get("myKey").get()); + System.out.println("Glide SET(myKey, yourValue): " + client.set("myKey", "yourValue").get()); + System.out.println("Glide GET(myKey): " + client.get("myKey").get()); + System.out.println("Glide GET(invalid): " + client.get("invalid").get()); + + Object customGetMyKey = client.customCommand(new String[] {"get", "myKey"}).get(); + System.out.println("Glide CUSTOM_COMMAND(get, myKey): " + customGetMyKey); + + Object customGetInvalid = client.customCommand(new String[] {"get", "invalid"}).get(); + System.out.println("Glide CUSTOM_COMMAND(get, invalid): " + customGetInvalid); + + } catch (ExecutionException | InterruptedException e) { + System.out.println("Glide example failed with an exception: "); + e.printStackTrace(); + } + } + + /** Redis-client settings */ + public static class ConnectionSettings { + public final String host; + public final int port; + public final boolean useSsl; + public final boolean clusterMode; + + public ConnectionSettings(String host, int port, boolean useSsl, boolean clusterMode) { + this.host = host; + this.port = port; + this.useSsl = useSsl; + this.clusterMode = clusterMode; + } + } +} diff --git a/java/examples/src/main/java/glide/examples/clients/GlideClient.java b/java/examples/src/main/java/glide/examples/clients/GlideClient.java new file mode 100644 index 0000000000..c4bd58ad64 --- /dev/null +++ b/java/examples/src/main/java/glide/examples/clients/GlideClient.java @@ -0,0 +1,27 @@ +package glide.examples.clients; + +import glide.api.RedisClient; +import glide.api.models.configuration.NodeAddress; +import glide.api.models.configuration.RedisClientConfiguration; +import glide.examples.ExamplesApp; +import java.util.concurrent.ExecutionException; + +/** Connect to Jedis client. See: https://github.com/redis/jedis */ +public class GlideClient { + public static RedisClient connectToGlide(ExamplesApp.ConnectionSettings connectionSettings) + throws ExecutionException, InterruptedException { + if (connectionSettings.clusterMode) { + throw new RuntimeException("Not implemented"); + } + RedisClientConfiguration config = + RedisClientConfiguration.builder() + .address( + NodeAddress.builder() + .host(connectionSettings.host) + .port(connectionSettings.port) + .build()) + .useTLS(connectionSettings.useSsl) + .build(); + return RedisClient.CreateClient(config).get(); + } +} diff --git a/java/examples/src/main/java/glide/examples/clients/JedisClient.java b/java/examples/src/main/java/glide/examples/clients/JedisClient.java new file mode 100644 index 0000000000..55c788de10 --- /dev/null +++ b/java/examples/src/main/java/glide/examples/clients/JedisClient.java @@ -0,0 +1,30 @@ +package glide.examples.clients; + +import glide.examples.ExamplesApp; +import java.util.Set; +import redis.clients.jedis.DefaultJedisClientConfig; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisCluster; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.commands.JedisCommands; + +/** Connect to Jedis client. See: https://github.com/redis/jedis */ +public class JedisClient { + + public static JedisCommands connectToRedis(ExamplesApp.ConnectionSettings connectionSettings) { + JedisCommands jedis; + if (connectionSettings.clusterMode) { + jedis = + new JedisCluster( + Set.of(new HostAndPort(connectionSettings.host, connectionSettings.port)), + DefaultJedisClientConfig.builder().ssl(connectionSettings.useSsl).build()); + } else { + try (JedisPool pool = + new JedisPool( + connectionSettings.host, connectionSettings.port, connectionSettings.useSsl)) { + jedis = pool.getResource(); + } + } + return jedis; + } +} diff --git a/java/examples/src/main/java/glide/examples/clients/LettuceAsyncClient.java b/java/examples/src/main/java/glide/examples/clients/LettuceAsyncClient.java new file mode 100644 index 0000000000..4b63b106fa --- /dev/null +++ b/java/examples/src/main/java/glide/examples/clients/LettuceAsyncClient.java @@ -0,0 +1,45 @@ +package glide.examples.clients; + +import glide.examples.ExamplesApp; +import io.lettuce.core.AbstractRedisClient; +import io.lettuce.core.RedisClient; +import io.lettuce.core.RedisURI; +import io.lettuce.core.api.StatefulConnection; +import io.lettuce.core.api.StatefulRedisConnection; +import io.lettuce.core.api.async.RedisStringAsyncCommands; +import io.lettuce.core.cluster.RedisClusterClient; +import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; +import java.time.Duration; + +/** Connect to lettuce client - see: https://lettuce.io/ */ +public class LettuceAsyncClient { + static final int ASYNC_OPERATION_TIMEOUT_SEC = 1; + + private AbstractRedisClient client; + public RedisStringAsyncCommands asyncCommands; + private StatefulConnection connection; + + public LettuceAsyncClient(ExamplesApp.ConnectionSettings connectionSettings) { + RedisURI uri = + RedisURI.builder() + .withHost(connectionSettings.host) + .withPort(connectionSettings.port) + .withSsl(connectionSettings.useSsl) + .build(); + if (!connectionSettings.clusterMode) { + client = RedisClient.create(uri); + connection = ((RedisClient) client).connect(); + asyncCommands = ((StatefulRedisConnection) connection).async(); + } else { + client = RedisClusterClient.create(uri); + connection = ((RedisClusterClient) client).connect(); + asyncCommands = ((StatefulRedisClusterConnection) connection).async(); + } + connection.setTimeout(Duration.ofSeconds(ASYNC_OPERATION_TIMEOUT_SEC)); + } + + public void closeConnection() { + connection.close(); + client.shutdown(); + } +} diff --git a/java/settings.gradle b/java/settings.gradle index 6d5e31d8a0..d93b818e15 100644 --- a/java/settings.gradle +++ b/java/settings.gradle @@ -2,4 +2,5 @@ rootProject.name = 'glide' include 'client' include 'integTest' +include 'examples' include 'benchmarks'