Skip to content

Asynchronous API (4.0)

Mark Paluch edited this page Jul 9, 2015 · 10 revisions

lettuce is built on netty that is a multithreaded, event-driven IO framework. All communication is handled asynchronously. Every command sent to Redis using the asynchronous API creates a CompleteableFuture that can be cancelled, awaited and listened. You obtain the async API by calling the connectAsync() method of the RedisClient (or RedisClusterClient.connectClusterAsync).

There are several ways how to wait or get notified in case a future completes:

  1. RedisFuture.get() / RedisFuture.get(long timeout, TimeUnit unit)
  2. while(!RedisFuture.isDone())
  3. RedisFuture.await(long timeout, TimeUnit unit)
  4. RedisFuture.thenAccept(Consumer<? super T> action)

Futures of lettuce 4.0 also carry exceptions, if any occurred. If you call the get() method and an exception occurred, this exception will be rethrown wrapped within an ExecutionException (this is different to lettuce 3.x). You can find more details within the Javadoc on CompletionStage

Synchronization using RedisFuture.get()

You can fire this way one or more commands and wait until the execution completes. If you use RedisFuture.get() the system will wait indefinitely and block your call. RedisFuture.get(long timeout, TimeUnit unit) will wait at most until the specified timeout. If the result comes back earlier, so you call will also continue earlier. If the timeout exceeds, you will receive a TimeoutException.

Synchronization using isDone()

In this style, you are using the Future whether it's done. You can poll, wait or even do other things until your future comes back. isDone is a non-blocking call.

Waiting using await(long timeout, TimeUnit unit)

You can specify a maximal waiting time, like in the get(long timeout, TimeUnit unit) example. The difference to get() is, that await(long timeout, TimeUnit unit) will come back with a boolean value in every case. So if the execution takes longer than the timeout, await will return false instead of a TimeoutException. After a result of true you can call get() and you'll receive the return value immediately.

Chaining

You can design your flow also completely asynchronous using functions and consumers. You subscribe to an individual future using CompletionStage methods.

Exceptions

Any Redis errors will cause to throw an ExecutionException on calling get().

Examples

Basic operations

RedisStringAsyncCommands<String, String> async = client.connect().async();
RedisFuture<String> set = async.set("key", "value");
RedisFuture<String> get = async.get("key");

set.get() == "OK"
get.get() == "value"

Waiting for a future with a timeout

RedisStringAsyncCommands<String, String> async = client.connect().async();
RedisFuture<String> set = async.set("key", "value");
RedisFuture<String> get = async.get("key");

set.await(1, SECONDS) == true
set.get() == "OK"
get.get(1, TimeUnit.MINUTES) == "value"

Using listeners for a future

RedisStringAsyncCommands<String, String> async = client.connect().async();
RedisFuture<String> set = async.set("key", "value");

Runnable listener = new Runnable() {
    @Override
    public void run() {
            ...;
    }
};

set.thenRun(listener);
Clone this wiki locally