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

Allow Type Reference in the Redis data source #34841

Merged
merged 1 commit into from
Jul 19, 2023
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
105 changes: 71 additions & 34 deletions docs/src/main/asciidoc/redis-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Typically, we recommend:

This extension provides imperative and reactive APIs and low-level and high-level (type-safe) clients.

== Installation
== Use the Redis Client

If you want to use this extension, you need to add the `io.quarkus:quarkus-redis` extension first.
In your `pom.xml` file, add:
Expand Down Expand Up @@ -85,7 +85,7 @@ To help you select the suitable API for you, here are some recommendations:
* If you have existing Vert.x code, use `io.vertx.redis.client.RedisAPI`
* If you need to emit custom commands, you can either use the data sources (reactive or imperative) or the `io.vertx.mutiny.redis.client.Redis`.

== Default and named clients
== Inject the default and named clients

This extension lets you configure a _default_ Redis client/data sources or _named_ ones.
The latter is essential when you need to connect to multiple Redis instances.
Expand Down Expand Up @@ -135,7 +135,7 @@ public class RedisExample {

TIP: You can omit the `@Inject` annotation when using `@RedisClientName`.

== Connection to Redis
== Connect to the Redis server

The Redis extension can operate in 4 distinct modes:

Expand All @@ -151,7 +151,7 @@ The connection url is configured with the `quarkus.redis.hosts` (or `quarkus.red
quarkus.redis.hosts=redis://[:password@]host[:port][/db-number]
----

=== Unix Socket
=== Use Unix Socket

When using unix-socket, you need:

Expand All @@ -160,7 +160,7 @@ When using unix-socket, you need:
quarkus.redis.hosts=unix://[:password@]/domain/docker.sock[?select=db-number]
----

=== Sentinel Mode
=== Use the Sentinel Mode

When using Sentinel, you need to pass multiple _host urls_ and configure the client type to `sentinel`:

Expand All @@ -174,7 +174,7 @@ quarkus.redis.master-name=my-sentinel # Default is my-master
quarkus.redis.role=master # master is the default
----

=== Cluster Mode
=== Use the Cluster Mode

When using Redis in cluster mode, you need to pass multiple _host urls_, configure the client type to `cluster` and configure the `replicas` mode:

Expand All @@ -185,7 +185,7 @@ quarkus.redis.client-type=cluster
quarkus.redis.replicas=share
----

=== Replication Mode
=== Use the replication Mode

When using the replication mode, you need to pass a single host url and configure the type to be `replication`:

Expand All @@ -195,7 +195,7 @@ quarkus.redis.hosts=redis://localhost:7000
quarkus.redis.client-type=replication
----

=== Redis Cloud
=== Connect to Redis Cloud

To connect to redis cloud, you need the following properties:

Expand All @@ -205,14 +205,21 @@ quarkus.redis.hosts=<the redis cloud url such as redis://redis-12436.c14.us-east
quarkus.redis.password=<the password>
----

=== Authentication
=== Use TLS

To use TLS, you need to:

1. Set the `quarkus.redis.tls.enabled=true` property
2. Make sure that your URL starts with `rediss://` (with two `s`)

=== Configure the authentication

The Redis password can be set in the `redis://` URL or with the `quarkus.redis.password` property.
We recommend the latter, and if possible, using secrets or an environment variable to configure the password.

The associated environment variable is `QUARKUS_REDIS_PASSWORD`, or `QUARKUS_REDIS_<NAME>_PASSWORD` for named clients.

== Quarkus client API for data sources
== Use Redis data sources

Quarkus exposes a high-level API on top of Redis.
This API is type-safe and structured around the notion of _group_, inherited from the https://redis.io/commands/command-docs/[Redis command organization].
Expand Down Expand Up @@ -263,7 +270,6 @@ The `ReactiveRedisDataSource` is implemented on top of the `io.vertx.mutiny.redi

As mentioned above, the API is divided into groups:

- bitmap - `.bitmap()`
- bitmap - `.bitmap()`
- key (generic) - `.key()`
- geo - `.geo(memberType)`
Expand All @@ -282,7 +288,8 @@ As mentioned above, the API is divided into groups:
- count-min - `.countmin()` (requires the https://redis.com/modules/redis-bloom/[RedisBloom] module on the server side, which also provides the count-min filter commands)
- top-k - `.topk()` (requires the https://redis.com/modules/redis-bloom/[RedisBloom] module on the server side, which also provides the top-k filter commands)
- graph - `.graph()` (requires the https://redis.com/modules/redis-graph/[RedisGraph] module on the server side).
These commands are marked as experimental, as we would need feedback before making them stable.
These commands are marked as experimental.
Also the module has been declared _end of life_ by https://redis.com/blog/redisgraph-eol/[Redis].
- search - `.search()` (requires the https://redis.com/modules/redis-search/[RedisSearch] module on the server side).
- auto-suggest - `.autosuggest()` (requires the https://redis.com/modules/redis-search/[RedisSearch] module on the server side).
- time-series - `.timeseries()` (requires the https://redis.com/modules/redis-timeseries/[Redis Time Series] module on the server side).
Expand Down Expand Up @@ -321,7 +328,7 @@ This object has three type parameters: the type of the key, the type of the fiel
<3> Use the created `commands` to associate the field `field` with the value `value`
<4> Use the created `commands` to retrieve the field `field` value.

=== Serialization and Deserialization
=== Serializing and Deserializing data

The data source APIs handle the serialization and deserialization automatically.
By default, non-standard types are serialized into JSON and deserialized from JSON.
Expand Down Expand Up @@ -370,7 +377,37 @@ The `canHandle` method is called to check if the codec can handle a specific typ
The parameter received in the `encode` method matches that type.
The object returned by the `decode` method must also match that type.

=== The `value` group
=== Use type reference

Each group can be configured with `Class`, or with `TypeReference` objects.
`TypeReference` are useful when dealing with Java generics:

[source,java]
----
@ApplicationScoped
public class MyRedisService {

private static final String MY_KEY = "my-key";

private final HashCommands<String, String, List<Person>> commands;

public MyRedisService(RedisDataSource ds) {
commands = ds.hash(new TypeReference<List<Person>>(){});
}

public void set(String field, List<Person> value) {
commands.hset(MY_KEY, field, value);
}

public List<Person> get(String field) {
return commands.hget(MY_KEY, field);
}
}
----

IMPORTANT: You cannot use type references when using transaction. This is a known limitation.
machi1990 marked this conversation as resolved.
Show resolved Hide resolved

=== Manipulate cached and binary data with the `value` group

The `value` group is used to manipulate https://redis.io/docs/manual/data-types/#strings[Redis Strings].
Thus, this group is not limited to Java Strings but can be used for integers (like a counter) or binary content (like images).
Expand Down Expand Up @@ -563,7 +600,7 @@ public static class MyCache {
}
----

==== Redis transactions
==== Use Redis transactions

Redis transactions are slightly different from relational database transactions.
Redis transactions are a batch of commands executed altogether.
Expand Down Expand Up @@ -627,7 +664,7 @@ TransactionResult result = ds.withTransaction(tx -> {

IMPORTANT: You cannot use the pub/sub feature from within a transaction.

==== Optimistic locking
==== Implement the optimistic locking pattern

To use optimistic locking, you need to use a variant of the `withTransaction` method, allowing the execution of code before the transaction starts.
In other words, it will be executed as follows:
Expand Down Expand Up @@ -702,7 +739,7 @@ NOTE: You can also execute custom command in a transaction.

On startup, you can configure the Redis client to preload data into the Redis database.

=== Load scripts
=== Configure the load scripts

Specify the _load script_ you want to load using:

Expand All @@ -717,7 +754,7 @@ IMPORTANT: `load-script` is a build time property than cannot be overridden at r
Note that each client can have a different script, even a list of scripts.
In the case of a list, the data is imported in the list order (for example, first `actors.redis`, then `movies.redis` for the `my-redis` client).

=== Load Script format
=== Write load scripts

The `.redis` file follows a _one command per line_ format:

Expand Down Expand Up @@ -750,7 +787,7 @@ INCR counter
EXEC
----

=== Configuration
=== Configure the pre-loading

The data is loaded when the application starts.
By default, it drops the whole database before importing.
Expand All @@ -759,7 +796,7 @@ You can prevent this using `quarkus.redis.flush-before-load=false`.
Also, the import process only runs if the database is empty (no key).
You can force to import even if there is data using the `quarkus.redis.load-only-if-empty=false`

=== Dev/Test vs. Prod
=== Distinguish dev/test vs. prod when pre-loading

As mentioned above, in dev and test modes, Quarkus tries to import data by looking for the `src/main/resources/import.redis`.
This behavior is disabled in _prod_ mode, and if you want to import even in production, add:
Expand All @@ -773,20 +810,12 @@ Before importing in _prod_ mode, make sure you configured `quarkus.redis.flush-b

IMPORTANT: In dev mode, to reload the content of the `.redis` load scripts, you need to add: `%dev.quarkus.vertx.caching=false`

== Vert.x Redis Client
== Use the Vert.x redis client

In addition to the high-level API, you can use the Vertx Redis clients directly in your code.
The documentation of the Vert.x Redis Client is available on the https://vertx.io/docs/vertx-redis-client/java/[Vert.x Web Site].

== Redis Health Check

If you are using the `quarkus-smallrye-health` extension, `quarkus-redis` will automatically add a readiness health check to validate the connection to the Redis server.

So when you access the `/q/health/ready` endpoint of your application you will have information about the connection validation status.

This behavior can be disabled by setting the `quarkus.redis.health.enabled` property to `false` in your `application.properties`.

== Programmatic Redis Hosts
== Configure Redis hosts programmatically

The `RedisHostsProvider` programmatically provides redis hosts.
This allows for configuration of properties like redis connection password coming from other sources.
Expand Down Expand Up @@ -839,13 +868,21 @@ public static class MyExampleCustomizer implements RedisOptionsCustomizer {
}
----

=== Dev Services
=== Use the Redis Dev Services

See xref:redis-dev-services.adoc[Redis Dev Service].

== Redis client metrics
== Configure Redis observability

=== Enable the health checks

If you are using the `quarkus-smallrye-health` extension, `quarkus-redis` will automatically add a readiness health check to validate the connection to the Redis server.

So when you access the `/q/health/ready` endpoint of your application you will have information about the connection validation status.

This behavior can be disabled by setting the `quarkus.redis.health.enabled` property to `false` in your `application.properties`.

=== Enable metrics collection
=== Enable metrics

Redis client metrics are automatically enabled when the application also uses the xref:telemetry-micrometer.adoc[`quarkus-micrometer`] extension.
Micrometer collects the metrics of all the Redis clients implemented by the application.
Expand Down Expand Up @@ -905,7 +942,7 @@ The Redis client name can be found in the _tags_.

The metrics contain both the Redis connection pool metrics (`redis_pool_*`) and the metrics about the command execution (`redis_commands_*`) such as the number of command, successes, failures, and durations.

=== Disable metrics collection
=== Disable metrics

To disable the Redis client metrics when `quarkus-micrometer` is used, add the following property to the application configuration:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ public Uni<Void> invalidateAll() {
@Override
public Uni<Void> invalidateIf(Predicate<Object> predicate) {
return redis.send(Request.cmd(Command.KEYS).arg(getKeyPattern()))
.map(response -> marshaller.decodeAsList(response, String.class))
.<List<String>> map(response -> marshaller.decodeAsList(response, String.class))
.chain(new Function<List<String>, Uni<?>>() {
@Override
public Uni<?> apply(List<String> listOfKeys) {
Expand Down
Loading