### Start Redis Manually for Testing Source: https://github.com/redis/lettuce/blob/main/README.md Manually starts Redis instances required for running Lettuce tests. Use `make stop` to halt them. ```bash make start ``` -------------------------------- ### Functional Chaining Example Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md Illustrates functional chaining with reactive commands. This example adds keys to a set, gets a random key, and prints its type. ```java RedisStringReactiveCommands reactive = client.connect().reactive(); Flux.just("Ben", "Michael", "Mark") .flatMap(key -> commands.sadd("seen", key)) .flatMap(value -> commands.randomkey()) .flatMap(commands::type) .doOnNext(System.out::println).subscribe(); ``` -------------------------------- ### Basic Lettuce Setup for Vector Sets Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/vector-sets.md Establishes a connection to Redis and obtains a RedisVectorSetCommands instance for interacting with vector sets. ```java RedisURI redisURI = RedisURI.Builder.redis("localhost").withPort(6379).build(); RedisClient redisClient = RedisClient.create(redisURI); StatefulRedisConnection connection = redisClient.connect(); RedisVectorSetCommands vectorSet = connection.sync(); ``` -------------------------------- ### Get and Set Database Weights at Runtime Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/failover.md Shows how to retrieve the current active database and its weight, get the weight of a specific database by URI, and dynamically change a database's weight to influence failover. ```java StatefulRedisMultiDbConnection connection = client.connect(); // Get current active database and its weight RedisDatabase currentDb = connection.getCurrentDatabase(); float currentWeight = currentDb.getWeight(); System.out.println("Current active database weight: " + currentWeight); // Get weight for a specific database by endpoint RedisURI targetUri = RedisURI.create("redis://redis-west.example.com:6379"); RedisDatabase targetDb = connection.getDatabase(targetUri); float targetWeight = targetDb.getWeight(); System.out.println("Target database weight: " + targetWeight); // Change which database should be active by setting a higher weight // This will cause automatic failback to targetDb if failback is enabled targetDb.setWeight(currentWeight + 1.0f); ``` -------------------------------- ### Basic Redis Connection and Command Execution Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/connecting-redis.md Demonstrates creating a Redis client, establishing a connection, executing a GET command, and properly closing the connection and client. ```java RedisClient client = RedisClient.create("redis://localhost"); StatefulRedisConnection connection = client.connect(); RedisCommands commands = connection.sync(); String value = commands.get("foo"); ... connection.close(); client.shutdown(); ``` -------------------------------- ### Get and Use KeyCommands Instance Source: https://github.com/redis/lettuce/blob/main/docs/redis-command-interfaces.md Obtain an instance of your custom command interface (KeyCommands) from the factory. Use this instance to invoke Redis commands like GET. ```java public class SomeClient { KeyCommands commands; public SomeClient(RedisCommandFactory factory) { commands = factory.getCommands(KeyCommands.class); } public void doSomething() { String value = commands.get("Walter"); } } ``` -------------------------------- ### Execute Multiple Commands with Multi Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/transactions-multi.md Use `multi()` to start a transaction, queue commands, and `exec()` to execute them. The result is a list of results from each command. ```java redis.multi(); redis.set("one", "1"); redis.set("two", "2"); redis.mget("one", "two"); redis.llen(key); redis.exec(); // result: list("OK", "OK", list("1", "2"), 0L) ``` -------------------------------- ### Basic Async Set and Get Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/async-api.md Demonstrates a simple asynchronous SET and GET operation. Use .get() to retrieve the result, which blocks until the operation completes. ```java RedisAsyncCommands async = client.connect().async(); RedisFuture set = async.set("key", "value"); RedisFuture get = async.get("key"); set.get() == "OK" get.get() == "value" ``` -------------------------------- ### Command Naming Strategies Source: https://github.com/redis/lettuce/blob/main/docs/redis-command-interfaces.md Demonstrates how Lettuce derives Redis commands from method names, with examples of plain methods, @Command annotations, and @CommandNaming strategies. ```APIDOC ## Command Naming Strategies Lettuce provides two primary ways to derive a Redis command from a method name: 1. **Direct Method Name Derivation**: The command name is derived directly from the method name (e.g., `mget` maps to `MGET`). 2. **`@Command` Annotation**: A manually defined `@Command` annotation explicitly specifies the Redis command. ### Example Interface ```java public interface MixedCommands extends Commands { List mget(String... keys); @Command("MGET") List> mgetAsValues(String... keys); @CommandNaming(strategy = DOT) double nrRun(String key, int... indexes); } ``` - **Plain Command Method**: `mget(String... keys)` derives the command `MGET`. - **`@Command` Annotated Method**: `mgetAsValues(String... keys)` explicitly uses the `MGET` command due to the annotation's higher precedence. - **`@CommandNaming` Strategy**: `nrRun(String key, int... indexes)` uses the `DOT` strategy, mapping to `NR.RUN`. **Note**: Command names are resolved case-sensitively against `CommandType`. Lower-case command names in `@Command` can be used to resolve to unknown commands, potentially enforcing master-routing. ``` -------------------------------- ### Basic Redis Connection and Operation in Java Source: https://github.com/redis/lettuce/blob/main/docs/getting-started.md This example shows how to create a Redis client, establish a connection, execute a SET command, and then close the connection and client. Ensure you have the necessary imports. ```java import io.lettuce.core.*; ``` ```java RedisClient redisClient = RedisClient.create("redis://password@localhost:6379/0"); StatefulRedisConnection connection = redisClient.connect(); RedisCommands syncCommands = connection.sync(); syncCommands.set("key", "Hello, Redis!"); connection.close(); redisClient.shutdown(); ``` -------------------------------- ### Custom BitString Codec Example Source: https://github.com/redis/lettuce/blob/main/docs/integration-extension.md Provides an example of a custom `BitStringCodec` that extends `StringCodec` for decoding byte buffers into bit strings. It also shows how to use this codec with Lettuce commands. ```java public class BitStringCodec extends StringCodec { @Override public String decodeValue(ByteBuffer bytes) { StringBuilder bits = new StringBuilder(bytes.remaining() * 8); while (bytes.remaining() > 0) { byte b = bytes.get(); for (int i = 0; i < 8; i++) { bits.append(Integer.valueOf(b >>> i & 1)); } } return bits.toString(); } } StatefulRedisConnection connection = client.connect(new BitStringCodec()); RedisCommands redis = connection.sync(); redis.setbit(key, 0, 1); redis.setbit(key, 1, 1); redis.setbit(key, 2, 0); redis.setbit(key, 3, 0); redis.setbit(key, 4, 0); redis.setbit(key, 5, 1); redis.get(key) == "00100011" ``` -------------------------------- ### Basic Redis Connection and GET Command Source: https://github.com/redis/lettuce/blob/main/README.md Establishes a synchronous connection to a Redis instance and retrieves a value using the GET command. Requires `RedisClient` and `StatefulRedisConnection`. ```java RedisClient client = RedisClient.create("redis://localhost"); StatefulRedisConnection connection = client.connect(); RedisStringCommands sync = connection.sync(); String value = sync.get("key"); ``` -------------------------------- ### Async Set and Get with Timeouts Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/async-api.md Shows how to perform asynchronous SET and GET operations with specified timeouts. Use .await() for the SET operation and .get(timeout, unit) for the GET operation. ```java RedisAsyncCommands async = client.connect().async(); RedisFuture set = async.set("key", "value"); RedisFuture get = async.get("key"); set.await(1, SECONDS) == true set.get() == "OK" get.get(1, TimeUnit.MINUTES) == "value" ``` -------------------------------- ### HGETALL Command Output - Java Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/custom-commands.md Example of creating a command for HGETALL with a Map output, using StringCodec. ```java StringCodec codec = StringCodec.UTF8; Command> command = new Command<>(CommandType.HGETALL, new MapOutput<>(codec), new CommandArgs<>(codec).addKey(key)); ``` -------------------------------- ### Asynchronous Redis SET and GET Commands Source: https://github.com/redis/lettuce/blob/main/README.md Demonstrates the asynchronous API for setting and getting values. Uses `RedisFuture` for non-blocking operations. Ensure `LettuceFutures.awaitAll` is used for synchronization. ```java StatefulRedisConnection connection = client.connect(); RedisStringAsyncCommands async = connection.async(); RedisFuture set = async.set("key", "value"); RedisFuture get = async.get("key"); LettuceFutures.awaitAll(set, get) == true set.get() == "OK" get.get() == "value" ``` -------------------------------- ### Start Java Flight Recording Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/events.md Start a Java Flight Recording session to capture JFR events by providing the StartFlightRecording JVM option. ```shell java -XX:StartFlightRecording=filename=recording.jfr,duration=10s … ``` -------------------------------- ### Basic Lettuce Setup for Redis Search Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/redis-search.md Establishes a connection to Redis using Lettuce and obtains a RediSearchCommands instance for interacting with Redis Search functionalities. Ensure Redis is running and accessible. ```java RedisURI redisURI = RedisURI.Builder.redis("localhost").withPort(6379).build(); RedisClient redisClient = RedisClient.create(redisURI); StatefulRedisConnection connection = redisClient.connect(); RediSearchCommands search = connection.sync(); ``` -------------------------------- ### Build Lettuce from Source (Git Clone and Make) Source: https://github.com/redis/lettuce/blob/main/README.md Clones the Lettuce repository and uses `make` commands to build and run tests. Requires Git and Make. Starts Redis instances for testing. ```bash $ git clone https://github.com/redis/lettuce.git $ cd lettuce/ $ make start ``` -------------------------------- ### MixedCommands Interface Example Source: https://github.com/redis/lettuce/blob/main/docs/redis-command-interfaces.md Demonstrates defining Redis commands with `@Command` annotation, including index-based and name-based parameter references. ```APIDOC ## MixedCommands ### Description An example interface showing how to define Redis commands using the `@Command` annotation with different parameter referencing styles. ### Interface Definition ```java interface MixedCommands extends Commands { @Command("SET ?1 ?0") String set(String value, String key); @Command("NR.OBSERVE :key :in -> :out TRAIN") List nrObserve(@Param("key") String key, @Param("in") int[] in, @Param("out") int... out); } ``` ### Parameter Referencing - **Index-based**: `?0`, `?1`, ... (zero-based) - **Name-based**: `:key`, `:in`, ... (requires parameter names or `@Param` annotation) ### Notes - Parameters can be referenced multiple times. - Unreferenced parameters are appended as arguments after the last command segment. ``` -------------------------------- ### Connect to Standalone Master/Replica Source: https://github.com/redis/lettuce/blob/main/docs/ha-sharding.md Establishes a connection to a standalone Master/Replica setup. The initial URI can point to either a master or a replica node, and Lettuce will discover the rest of the topology. ```java RedisClient redisClient = RedisClient.create(); StatefulRedisMasterReplicaConnection connection = MasterReplica.connect(redisClient, StringCodec.UTF8, RedisURI.create("redis://localhost")); connection.setReadFrom(ReadFrom.MASTER_PREFERRED); System.out.println("Connected to Redis"); connection.close(); redisClient.shutdown(); ``` -------------------------------- ### HKEYS Command Output - Java Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/custom-commands.md Example of creating a command for HKEYS with a List output, using StringCodec. ```java StringCodec codec = StringCodec.UTF8; Command> command = new Command<>(CommandType.HKEYS, new KeyListOutput<>(codec), new CommandArgs<>(codec).addKey(key)); ``` -------------------------------- ### PING Command Output - Java Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/custom-commands.md Example of creating a command for the PING command with a String output type. ```java Command command = new Command<>(CommandType.PING, new StatusOutput<>(StringCodec.UTF8)); ``` -------------------------------- ### Blocking SET Command Example Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md Demonstrates a blocking SET command using the reactive API. Use block() when you need to wait for the result. ```java RedisStringReactiveCommands reactive = client.connect().reactive(); Mono set = reactive.set("key", "value"); set.block(); ``` -------------------------------- ### Configure MultiDbClient for Failover Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/failover.md Configure databases with weights, where a higher weight signifies a higher priority. This example sets up two databases, 'redis-east' as primary and 'redis-west' as secondary, for failover. ```java import io.lettuce.core.RedisURI; import io.lettuce.core.failover.api.DatabaseConfig; import io.lettuce.core.failover.MultiDbClient; import io.lettuce.core.failover.api.MultiDbOptions; import io.lettuce.core.failover.api.StatefulRedisMultiDbConnection; // Configure databases with weights (higher weight = higher priority) // redis-east RedisURI eastUri = RedisURI.builder() .withHost("redis-east.example.com") .withPort(6379) .withPassword("secret".toCharArray()) .build(); DatabaseConfig east = DatabaseConfig.builder(eastUri) .weight(1.0f) // Primary database .build(); // redis-west RedisURI westUri = RedisURI.builder() .withHost("redis-west.example.com") .withPort(6379) .withPassword("secret".toCharArray()) .build(); DatabaseConfig west = DatabaseConfig.builder(westUri) .weight(0.5f) // Secondary database .build(); // Create the multi-database client MultiDbClient client = MultiDbClient.create(Arrays.asList(east, west)); // Connect and use like a regular Redis connection StatefulRedisMultiDbConnection connection = client.connect(); // Execute commands asynchronously - they go to the highest-weighted healthy database connection.async().set("key", "value"); String value = connection.async().get("key").get(); // Clean up connection.close(); client.shutdown(); ``` -------------------------------- ### Non-blocking SET Command Example Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md Demonstrates a non-blocking SET command using the reactive API. Subscribe to process the result asynchronously. ```java RedisStringReactiveCommands reactive = client.connect().reactive(); Mono set = reactive.set("key", "value"); set.subscribe(); ``` -------------------------------- ### Streaming HGETALL with KeyValueStreamingChannel Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/streaming-api.md Example of using KeyValueStreamingChannel to process HGETALL results as key-value pairs arrive. Implement the onKeyValue method to handle each pair. ```java Long count = redis.hgetall(new KeyValueStreamingChannel() { @Override public void onKeyValue(String key, String value) { ... } }, key); ``` -------------------------------- ### Connect via Unix Domain Socket (Builder) Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/native-transports.md Example of creating a RedisURI using the builder pattern to specify a Unix domain socket path, password, and database. ```java RedisURI redisUri = RedisURI.Builder .socket("/tmp/redis") .withPassword("authentication") .withDatabase(2) .build(); RedisClient client = RedisClient.create(redisUri); ``` -------------------------------- ### Connect via Unix Domain Socket (URI String) Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/native-transports.md Example of creating a RedisURI directly from a URI string specifying a Unix domain socket path. ```java RedisURI redisUri = RedisURI.create("redis-socket:///tmp/redis"); RedisClient client = RedisClient.create(redisUri); ``` -------------------------------- ### Set up RedisCommandFactory Source: https://github.com/redis/lettuce/blob/main/docs/redis-command-interfaces.md Instantiate RedisClient and connect to establish a connection. Then, create a RedisCommandFactory using the connection to generate command interface proxies. ```java RedisClient client = … RedisCommandFactory factory = new RedisCommandFactory(client.connect()); ``` -------------------------------- ### Filter items starting with 'M' Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md Use the `filter` operator to include only items that satisfy a given predicate. This example filters strings to keep only those starting with 'M'. ```java Flux.just("Ben", "Michael", "Mark") .filter(s -> s.startsWith("M")) .flatMap(commands::get) .subscribe(value -> System.out.println("Got value: " + value)); ``` -------------------------------- ### Using Listeners for Asynchronous Operations Source: https://github.com/redis/lettuce/wiki/Asynchronous-Connections Provides an example of attaching a listener to an asynchronous operation to execute code upon completion. This is an alternative to blocking with `get()`. ```java RedisStringsConnection async = client.connectAsync(); RedisFuture set = async.set("key", "value"); Runnable listener = new Runnable() { @Override public void run() { ...; } }; set.addListener(listener, MoreExecutors.sameThreadExecutor()); ``` -------------------------------- ### Enable StartTLS Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/ssl-connections.md Configure the RedisURI to use StartTLS, which initiates a plain text connection and then upgrades it to SSL. StartTLS is disabled by default. ```java RedisURI redisUri = ... redisUri.setStartTls(true); ``` ```java RedisURI redisUri = RedisURI.Builder.redis(host(), sslPort()) .withSsl(true) .withStartTls(true) .build(); ``` -------------------------------- ### Building RedisURI with Authentication and Database Selection Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/connecting-redis.md Illustrates building a RedisURI using a builder pattern, including setting a password for authentication and specifying a database number. Remember to shut down the client. ```java RedisURI redisUri = RedisURI.Builder.redis("localhost") .withPassword("authentication") .withDatabase(2) .build(); RedisClient client = RedisClient.create(redisUri); // … client.shutdown(); ``` -------------------------------- ### Perform Asynchronous GET Operation Source: https://github.com/redis/lettuce/wiki/Asynchronous-Connections Retrieves the value associated with a key from Redis asynchronously using the `get` operation on an existing connection. ```java RedisFuture future = connection.get("key"); ``` -------------------------------- ### Building RedisURI with SSL Enabled Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/connecting-redis.md Demonstrates configuring a RedisURI for SSL connections by setting the `withSsl` option, along with authentication and database selection. The client must be shut down. ```java RedisURI redisUri = RedisURI.Builder.redis("localhost") .withSsl(true) .withPassword("authentication") .withDatabase(2) .build(); RedisClient client = RedisClient.create(redisUri); // … client.shutdown(); ``` -------------------------------- ### Chaining GET Operations for Multiple Keys Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md Uses flatMap to chain multiple asynchronous GET operations for keys emitted by a Flux, subscribing to each result. ```java Flux.just("Ben", "Michael", "Mark"). flatMap(key -> commands.get(key)). subscribe(value -> System.out.println("Got value: " + value)); ``` -------------------------------- ### Subscribe to GET Operation Result (Anonymous Class) Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md Performs a GET operation on a Redis key and subscribes to the result using an anonymous inner class to process the value. ```java commands.get("key").subscribe(new Consumer() { public void accept(String value) { System.out.println(value); } }); ``` -------------------------------- ### Set ClientOptions Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/client-options.md Demonstrates how to set ClientOptions for a Redis client. Options are immutable and inherited at connection creation. ```java client.setOptions(ClientOptions.builder() .autoReconnect(false) .pingBeforeActivateConnection(true) .build()); ``` -------------------------------- ### Connect to Pub/Sub and Add Listener Source: https://github.com/redis/lettuce/wiki/Pub-Sub-(3.x) Establishes a connection for Pub/Sub messaging and attaches a listener to handle events. Subscribe to channels after setting up the listener. ```java RedisPubSubConnection connection = client.connectPubSub() connection.addListener(new RedisPubSubListener() { ... }) connection.subscribe("channel") ``` -------------------------------- ### Subscribe to GET Operation Result (Lambda) Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md Performs a GET operation on a Redis key and subscribes to the result using a Java 8 lambda expression for concise value processing. ```java commands .get("key") .subscribe(value -> System.out.println(value)); ``` -------------------------------- ### Perform GET operation with Lettuce Async API Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/async-api.md Retrieves the value associated with a key using the asynchronous `GET` command. This returns a `RedisFuture` that represents the pending result. ```java RedisFuture future = commands.get("key"); ``` -------------------------------- ### Configure Micrometer Integration Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/observability.md Set up Micrometer for command latency recording. Requires Micrometer core dependency. Ensure `MeterRegistry` and `MicrometerOptions` are properly initialized. ```java MeterRegistry meterRegistry = …; MicrometerOptions options = MicrometerOptions.create(); ClientResources resources = ClientResources.builder().commandLatencyRecorder(new MicrometerCommandLatencyRecorder(meterRegistry, options)).build(); RedisClient client = RedisClient.create(resources); ``` -------------------------------- ### Initialize and Render Benchmarks Source: https://github.com/redis/lettuce/blob/main/docs/static/benchmarks/index.html Initializes benchmark data and renders it to the main element. Ensure the DOM is ready before calling. ```javascript const main = document.getElementById('main'); for (const {name, dataSet} of dataSets) { renderBenchSet(name, dataSet, main); } } renderAllChars(init()); // Start })(); ``` -------------------------------- ### Stop Redis Instances Source: https://github.com/redis/lettuce/blob/main/README.md Stops the Redis instances that were started manually for testing purposes. ```bash make stop ``` -------------------------------- ### Manage Suggestions in a Dictionary Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/redis-search.md Use `ftSuglen` to get the size of a suggestion dictionary and `ftSugdel` to delete a suggestion. ```java // Get suggestion dictionary size Long count = search.ftSuglen("autocomplete"); // Delete a suggestion Boolean deleted = search.ftSugdel("autocomplete", "old suggestion"); ``` -------------------------------- ### Creating RedisURI with Host, Port, and Timeout Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/connecting-redis.md Shows how to create a RedisURI instance specifying the host, port, and a connection timeout duration. Ensure the client is shut down when done. ```java RedisURI uri = new RedisURI("localhost", 6379, Duration.ofSeconds(20)); RedisClient client = RedisClient.create(uri); // … client.shutdown(); ``` -------------------------------- ### Create and Manage a SettableFuture Source: https://github.com/redis/lettuce/wiki/Asynchronous-Connections Demonstrates the lifecycle of a `SettableFuture`, showing how to create it, check its completion status, set a value, and retrieve the value. ```java SettableFuture future = SettableFuture.create(); System.out.println("Current state: " + future.isDone()); future.set("my value"); System.out.println("Current state: " + future.isDone()); System.out.println("Got value: " + future.get()); ``` -------------------------------- ### Add and Remove Databases Dynamically Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/failover.md Demonstrates how to add a new database configuration and remove an existing one from a multi-database connection at runtime. ```java StatefulRedisMultiDbConnection connection = client.connect(); // Add a new database RedisURI newDb = RedisURI.create("redis://new-server:6379"); DatabaseConfig newConfig = DatabaseConfig.builder(newDb) .weight(0.8f) .build(); connection.addDatabase(newConfig); // Remove a database connection.removeDatabase(existingUri); ``` -------------------------------- ### Explain Query Execution Plan Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/redis-search.md Use `ftExplain` to understand how Redis Search executes a query. An optional `ExplainArgs` object can specify the dialect for detailed plans. ```java // Basic query explanation String plan = search.ftExplain("products-idx", "@title:wireless"); // Detailed explanation with dialect ExplainArgs explainArgs = ExplainArgs.builder() .dialect(QueryDialects.DIALECT2) .build(); String detailedPlan = search.ftExplain("products-idx", "@title:wireless", explainArgs); System.out.println("Execution plan: " + detailedPlan); ``` -------------------------------- ### Fire & Forget Dispatch - Java Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/custom-commands.md Example of dispatching a PING command using the Fire & Forget pattern, which discards the output. ```java StatefulRedisConnection connection = redis.getStatefulConnection(); connection.dispatch(CommandType.PING, VoidOutput.create()); ``` -------------------------------- ### Create Default Client Resources Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/client-resources.md Use the `create()` factory method on `DefaultClientResources` to instantiate `ClientResources` with default settings. This is suitable for most common use cases. ```java ClientResources res = DefaultClientResources.create(); ``` -------------------------------- ### Value Compression with GZIP Source: https://github.com/redis/lettuce/blob/main/docs/integration-extension.md Demonstrates how to connect to Redis with value compression enabled using GZIP. This is useful for storing larger textual data structures. ```java StatefulRedisConnection connection = client.connect( CompressionCodec.valueCompressor(new SerializedObjectCodec(), CompressionCodec.CompressionType.GZIP)).sync(); ``` -------------------------------- ### Get Suggestions from a Dictionary Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/redis-search.md Use `ftSugget` to retrieve suggestions. Options include fuzzy matching, limiting results, and including scores/payloads. ```java // Basic suggestion retrieval List> suggestions = search.ftSugget("autocomplete", "head"); // Advanced suggestion options SugGetArgs getArgs = SugGetArgs.builder() .fuzzy() // Enable fuzzy matching .max(5) // Limit to 5 suggestions .withScores() // Include scores .withPayloads() // Include payloads .build(); List> results = search.ftSugget("autocomplete", "head", getArgs); for (Suggestion suggestion : results) { System.out.println("Suggestion: " + suggestion.getValue()); System.out.println("Score: " + suggestion.getScore()); System.out.println("Payload: " + suggestion.getPayload()); } ``` -------------------------------- ### Get Index Information and List Indexes in Java Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/redis-search.md Retrieve statistics about a specific index or list all available indexes in Redis Search. ```java // Get index information Map info = search.ftInfo("products-idx"); System.out.println("Index size: " + info.get("num_docs")); System.out.println("Index memory: " + info.get("inverted_sz_mb") + " MB"); // List all indexes List indexes = search.ftList(); ``` -------------------------------- ### Vector Set Best Practices in Java Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/vector-sets.md Demonstrates best practices for using Redis vector sets, such as choosing appropriate quantization, batching operations, using descriptive names, and monitoring set size and performance. ```java public class VectorSetBestPractices { // 1. Use appropriate quantization for your use case public void chooseQuantization() { // High precision needed (scientific, financial) VAddArgs highPrecision = VAddArgs.Builder .quantizationType(QuantizationType.NO_QUANTIZATION) .build(); // Balanced performance (most applications) VAddArgs balanced = VAddArgs.Builder .quantizationType(QuantizationType.Q8) .build(); // Maximum speed/minimum memory (large scale) VAddArgs fast = VAddArgs.Builder .quantizationType(QuantizationType.BINARY) .build(); } // 2. Batch operations for better performance public void batchOperations(RedisVectorSetCommands vectorSet) { // Instead of individual adds, batch them List vectors = loadVectorData(); for (VectorData data : vectors) { vectorSet.vadd("batch_vectors", data.id, data.vector); if (!data.attributes.isEmpty()) { vectorSet.vsetattr("batch_vectors", data.id, data.attributes); } } } // 3. Use meaningful element names public void useDescriptiveNames(RedisVectorSetCommands vectorSet) { // Good: descriptive, hierarchical naming vectorSet.vadd("products", "electronics:laptop:dell:xps13", 0.1, 0.2, 0.3); vectorSet.vadd("users", "user:12345:preferences", 0.4, 0.5, 0.6); // Avoid: generic, non-descriptive names // vectorSet.vadd("data", "item1", 0.1, 0.2, 0.3); } // 4. Monitor vector set size and performance public void monitorVectorSet(RedisVectorSetCommands vectorSet, String key) { Long cardinality = vectorSet.vcard(key); Long dimensions = vectorSet.vdim(key); System.out.println("Vector set '" + key + "' stats:"); System.out.println(" Elements: " + cardinality); System.out.println(" Dimensions: " + dimensions); System.out.println(" Estimated memory: " + estimateMemoryUsage(cardinality, dimensions)); } private String estimateMemoryUsage(Long elements, Long dimensions) { // Rough estimation for Q8 quantization long bytesPerVector = dimensions * 1; // 1 byte per dimension for Q8 long totalBytes = elements * bytesPerVector; return String.format("~%.2f MB", totalBytes / (1024.0 * 1024.0)); } private List loadVectorData() { // Placeholder for loading vector data return new ArrayList<>(); } private static class VectorData { String id; double[] vector; String attributes; } } ``` -------------------------------- ### Set and Get Element Attributes Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/vector-sets.md Manage JSON attributes for elements using vsetattr to set, vgetattr to retrieve, and vClearAttributes to remove them. ```java // Set JSON attributes for an element String attributes = "{\"category\": \"electronics\", \"price\": 299.99, \"brand\": \"TechCorp\"}"; Boolean attrSet = vectorSet.vsetattr("products", "item:1", attributes); // Get attributes for an element String retrievedAttrs = vectorSet.vgetattr("products", "item:1"); System.out.println("Attributes: " + retrievedAttrs); // Clear all attributes for an element Boolean cleared = vectorSet.vClearAttributes("products", "item:1"); ``` -------------------------------- ### Configure Micrometer Tracing with ClientResources Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/observability.md Configure Micrometer tracing by creating a MicrometerTracing instance with an ObservationRegistry and then building ClientResources with the tracing configuration. ```java ObservationRegistry observationRegistry = …; MicrometerTracing tracing = new MicrometerTracing(observationRegistry, "Redis"); ClientResources resources = ClientResources.builder().tracing(tracing).build(); ``` -------------------------------- ### Perform Spell Checking Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/redis-search.md Use `ftSpellcheck` to get spelling corrections for a query. Advanced options include distance, term inclusion/exclusion, and dialect. ```java // Basic spell check List> corrections = search.ftSpellcheck("products-idx", "wireles hedphones"); // Advanced spell check with options SpellCheckArgs spellArgs = SpellCheckArgs.builder() .distance(2) // Maximum Levenshtein distance .terms("include", "dictionary") // Include terms from dictionary .terms("exclude", "stopwords") // Exclude stopwords .dialect(QueryDialects.DIALECT2) .build(); List> results = search.ftSpellcheck("products-idx", "wireles hedphones", spellArgs); for (SpellCheckResult result : results) { System.out.println("Original: " + result.getTerm()); for (SpellCheckResult.Suggestion suggestion : result.getSuggestions()) { System.out.println(" Suggestion: " + suggestion.getValue() + " (score: " + suggestion.getScore() + ")"); } } ``` -------------------------------- ### Initialize RedisCommandFactory with Codecs Source: https://github.com/redis/lettuce/blob/main/docs/redis-command-interfaces.md Instantiate RedisCommandFactory with a list of codecs. ByteArrayCodec and StringCodec (UTF-8) are common defaults. ```java RedisCommandFactory factory = new RedisCommandFactory(connection, Arrays.asList(new ByteArrayCodec(), new StringCodec(LettuceCharsets.UTF8))); ``` -------------------------------- ### Get the first emitted item Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md The `next()` operator is used to retrieve the first item emitted by the Publisher. It terminates after emitting the first item. ```java Flux.just("Ben", "Michael", "Mark") .next() .subscribe(value -> System.out.println("Got value: " + value)); ``` -------------------------------- ### Basic Asynchronous Operations Source: https://github.com/redis/lettuce/wiki/Asynchronous-Connections Shows basic asynchronous set and get operations using Lettuce. Futures are used to represent the results of these operations. ```java RedisStringsConnection async = client.connectAsync(); RedisFuture set = async.set("key", "value"); RedisFuture get = async.get("key"); set.get() == "OK" get.get() == "value" ``` -------------------------------- ### SerializedObjectCodec Implementation Source: https://github.com/redis/lettuce/blob/main/docs/integration-extension.md An example implementation of a `RedisCodec` for serializing and deserializing Java objects. This codec handles the conversion between Java objects and byte buffers. ```java public class SerializedObjectCodec implements RedisCodec { private Charset charset = Charset.forName("UTF-8"); @Override public String decodeKey(ByteBuffer bytes) { return charset.decode(bytes).toString(); } @Override public Object decodeValue(ByteBuffer bytes) { try { byte[] array = new byte[bytes.remaining()]; bytes.get(array); ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(array)); return is.readObject(); } catch (Exception e) { return null; } } @Override public ByteBuffer encodeKey(String key) { return charset.encode(key); } @Override public ByteBuffer encodeValue(Object value) { try { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ObjectOutputStream os = new ObjectOutputStream(bytes); os.writeObject(value); return ByteBuffer.wrap(bytes.toByteArray()); } catch (IOException e) { return ByteBuffer.wrap(new byte[0]); } } } ``` -------------------------------- ### Basic Redis Connection and Operation in Java Source: https://github.com/redis/lettuce/wiki/Getting-started-(3.x) This Java code demonstrates how to establish a connection to a Redis server using Lettuce, set a key-value pair, and properly close the connection and shut down the client. ```java import com.lambdaworks.redis.*; ``` ```java RedisClient redisClient = new RedisClient(RedisURI.create("redis://password@localhost:6379/0")); RedisConnection connection = redisClient.connect(); connection.set("key", "Hello, Redis!"); connection.close(); redisClient.shutdown(); ``` -------------------------------- ### Connect to Redis Standalone over SSL Source: https://github.com/redis/lettuce/blob/main/docs/advanced-usage/ssl-connections.md Configure RedisURI to enable SSL for a standalone Redis connection. This example also sets a password and database. ```java RedisURI redisUri = RedisURI.Builder.redis("localhost") .withSsl(true) .withPassword("authentication") .withDatabase(2) .build(); RedisClient client = RedisClient.create(redisUri); ``` -------------------------------- ### Create RedisURI by Setting Values Directly Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/connecting-redis.md Instantiate RedisURI by directly providing host, port, and timeout values. ```java new RedisURI("localhost", 6379, 60, TimeUnit.SECONDS); ``` -------------------------------- ### Get the last emitted item Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md The `last()` operator retrieves the very last item emitted by the Publisher. If the Publisher is empty, it completes without emitting any item. ```java Flux.just("Ben", "Michael", "Mark") .last() .subscribe(value -> System.out.println("Got value: " + value)); ``` -------------------------------- ### Waiting for Futures with Timeout Source: https://github.com/redis/lettuce/wiki/Asynchronous-Connections Illustrates how to wait for asynchronous operations to complete within a specified timeout. This includes using `await` and `get` with time units. ```java RedisStringsConnection async = client.connectAsync(); RedisFuture set = async.set("key", "value"); RedisFuture get = async.get("key"); set.await(1, SECONDS) == true set.get() == "OK" get.get(1, TimeUnit.MINUTES) == "value" ``` -------------------------------- ### Redis Transaction Example Source: https://github.com/redis/lettuce/blob/main/docs/user-guide/reactive-api.md Shows how to execute commands within a Redis transaction using the reactive API. Commands are queued after MULT and executed with EXEC. ```java RedisReactiveCommands reactive = client.connect().reactive(); reactive.multi().doOnSuccess(s -> { reactive.set("key", "1").doOnNext(s1 -> System.out.println(s1)).subscribe(); reactive.incr("key").doOnNext(s1 -> System.out.println(s1)).subscribe(); }).flatMap(s -> reactive.exec()) .doOnNext(transactionResults -> System.out.println(transactionResults.wasRolledBack())) .subscribe(); ``` -------------------------------- ### Run Lettuce Tests Source: https://github.com/redis/lettuce/blob/main/README.md Executes the test suite for Lettuce using the `make test` command. This requires a successful build and running Redis instances. ```bash make test ``` -------------------------------- ### Initialize Benchmark Data Collection Source: https://github.com/redis/lettuce/blob/main/docs/static/benchmarks/index.html Collects and organizes benchmark entries per test case. It groups results by benchmark name, storing commit, date, tool, and bench details. ```javascript 'use strict'; (function() { // Colors from https://github.com/github/linguist/blob/master/lib/linguist/languages.yml const toolColors = { cargo: '#dea584', go: '#00add8', benchmarkjs: '#f1e05a', benchmarkluau: '#000080', pytest: '#3572a5', googlecpp: '#f34b7d', catch2: '#f34b7d', julia: '#a270ba', jmh: '#b07219', benchmarkdotnet: '#178600', customBiggerIsBetter: '#38ff38', customSmallerIsBetter: '#ff3838', _: '#333333' }; function init() { function collectBenchesPerTestCase(entries) { const map = new Map(); for (const entry of entries) { const {commit, date, tool, benches} = entry; for (const bench of benches) { const result = { commit, date, tool, bench }; const arr = map.get(bench.name); if (arr === undefined) { map.set(bench.name, [result]); } else { arr.push(result); } } } return map; } const data = window.BENCHMARK_DATA; // Render header document.getElementById('last-update').textContent = new Date(data.lastUpdate).toString(); const repoLink = document.getElementById('repository-link'); repoLink.href = data.repoUrl; repoLink.textContent = data.repoUrl; // Render footer document.getElementById('dl-button').onclick = () => { const dataUrl = 'data:,' + JSON.stringify(data, null, 2); const a = document.createElement('a'); a.href = dataUrl; a.download = 'benchmark_data.json'; a.click(); }; // Prepare data points for charts return Object.keys(data.entries).map(name => ({ name, dataSet: collectBenchesPerTestCase(data.entries[name]), })); } function renderAllChars(dataSets) { function renderGraph(parent, name, dataset) { const canvas = document.createElement('canvas'); canvas.className = 'benchmark-chart'; parent.appendChild(canvas); const color = toolColors[dataset.length > 0 ? dataset[0].tool : '_']; const data = { labels: dataset.map(d => d.commit.id.slice(0, 7)), datasets: [ { label: name, data: dataset.map(d => d.bench.value), borderColor: color, backgroundColor: color + '60', // Add alpha for #rrggbbaa }, ], }; const options = { scales: { xAxes: [ { scaleLabel: { display: true, labelString: 'commit', }, } ], yAxes: [ { scaleLabel: { display: true, labelString: dataset.length > 0 ? dataset[0].bench.unit : '', }, ticks: { beginAtZero: true, } } ], }, tooltips: { callbacks: { afterTitle: items => { const {index} = items[0]; const data = dataset[index]; return '\n' + data.commit.message + '\n\n' + data.commit.timestamp + ' committed by @' + data.commit.committer.username + '\n'; }, label: item => { let label = item.value; const { range, unit } = dataset[item.index].bench; label += ' ' + unit; if (range) { label += ' (' + range + ')'; } return label; }, afterLabel: item => { const { extra } = dataset[item.index].bench; return extra ? '\n' + extra : ''; } } }, onClick: (_mouseEvent, activeElems) => { if (activeElems.length === 0) { return; } // XXX: Undocumented. How can we know the index? const index = activeElems[0]._index; const url = dataset[index].commit.url; window.open(url, '_blank'); }, }; new Chart(canvas, { type: 'line', data, options, }); } function renderBenchSet(name, benchSet, main) { const setElem = document.createElement('div'); setElem.className = 'benchmark-set'; main.appendChild(setElem); const nameElem = document.createElement('h1'); nameElem.className = 'benchmark-title'; nameElem.textContent = name; setElem.appendChild(nameElem); const graphsElem = document.createElement('div'); graphsElem.className = 'benchmark-graphs'; setElem.appendChild(graphsElem); for (const [benchName, benches] of benchSet.entries()) { renderGraph(graphsElem, benchName, benches) } } const main = docume ``` -------------------------------- ### CamelCase in Method Names Source: https://github.com/redis/lettuce/blob/main/docs/redis-command-interfaces.md Explains how CamelCase in method names is translated into Redis command segments, with examples using default behavior and the @CommandNaming annotation. ```APIDOC ## CamelCase in Method Names By default, command methods use the method name to derive the command type. For commands with multiple segments (e.g., `CLIENT SETNAME`), CamelCase in method names helps express word boundaries. ### Default CamelCase Translation Camel humps (changes in letter casing) are typically translated into spaces between command segments. For example, `clientSetname` translates to the `CLIENT SETNAME` command. ```java interface ServerCommands extends Commands { String clientSetname(String name); } ``` Invoking `clientSetname("myname")` will execute the Redis command `CLIENT SETNAME myname`. ### `@CommandNaming` Annotation Strategies The `@CommandNaming` annotation allows customization of how CamelCase is translated. ```java @CommandNaming(strategy = Strategy.DOT) interface MixedCommands extends Commands { @CommandNaming(strategy = Strategy.SPLIT) String clientSetname(String name); @CommandNaming(strategy = Strategy.METHOD_NAME) String mSet(String key1, String value1, String key2, String value2); double nrRun(String key, int... indexes); } ``` **Available Strategies:** - **`SPLIT`**: Splits camel-case method names into multiple command segments. `clientSetname` executes `CLIENT SETNAME`. This is the default strategy. - **`METHOD_NAME`**: Uses the method name as-is. `mSet` executes `MSET`. - **`DOT`**: Translates camel-case method names into dot-notation, recommended for module-provided commands. `nrRun` executes `NR.RUN`. ```