diff --git a/docs/src/main/asciidoc/redis-reference.adoc b/docs/src/main/asciidoc/redis-reference.adoc index f802c34766e96..187cf380812cd 100644 --- a/docs/src/main/asciidoc/redis-reference.adoc +++ b/docs/src/main/asciidoc/redis-reference.adoc @@ -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: @@ -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. @@ -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: @@ -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: @@ -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`: @@ -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: @@ -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`: @@ -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: @@ -205,14 +205,21 @@ quarkus.redis.hosts= ---- -=== 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__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]. @@ -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)` @@ -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). @@ -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. @@ -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> commands; + + public MyRedisService(RedisDataSource ds) { + commands = ds.hash(new TypeReference>(){}); + } + + public void set(String field, List value) { + commands.hset(MY_KEY, field, value); + } + + public List get(String field) { + return commands.hget(MY_KEY, field); + } +} +---- + +IMPORTANT: You cannot use type references when using transaction. This is a known limitation. + +=== 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). @@ -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. @@ -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: @@ -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: @@ -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: @@ -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. @@ -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: @@ -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. @@ -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. @@ -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: diff --git a/extensions/redis-cache/runtime/src/main/java/io/quarkus/cache/redis/runtime/RedisCacheImpl.java b/extensions/redis-cache/runtime/src/main/java/io/quarkus/cache/redis/runtime/RedisCacheImpl.java index 79ea2d1f47f1f..7ba1c30da0eed 100644 --- a/extensions/redis-cache/runtime/src/main/java/io/quarkus/cache/redis/runtime/RedisCacheImpl.java +++ b/extensions/redis-cache/runtime/src/main/java/io/quarkus/cache/redis/runtime/RedisCacheImpl.java @@ -283,7 +283,7 @@ public Uni invalidateAll() { @Override public Uni invalidateIf(Predicate predicate) { return redis.send(Request.cmd(Command.KEYS).arg(getKeyPattern())) - .map(response -> marshaller.decodeAsList(response, String.class)) + .> map(response -> marshaller.decodeAsList(response, String.class)) .chain(new Function, Uni>() { @Override public Uni apply(List listOfKeys) { diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/ReactiveRedisDataSource.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/ReactiveRedisDataSource.java index b898666b7edc5..abf6899a3382d 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/ReactiveRedisDataSource.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/ReactiveRedisDataSource.java @@ -1,8 +1,12 @@ package io.quarkus.redis.datasource; +import static io.quarkus.redis.runtime.datasource.Marshaller.STRING_TYPE_REFERENCE; + import java.util.function.BiFunction; import java.util.function.Function; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.autosuggest.ReactiveAutoSuggestCommands; import io.quarkus.redis.datasource.bitmap.ReactiveBitMapCommands; import io.quarkus.redis.datasource.bloom.ReactiveBloomCommands; @@ -165,6 +169,25 @@ Uni> withTransaction(Function ReactiveHashCommands hash(Class redisKeyType, Class fieldType, Class valueType); + /** + * Gets the object to execute commands manipulating hashes (a.k.a. {@code Map<F, V>}). + *

+ * If you want to use a hash of {@code <String -> Person>} stored using String identifier, you would use: + * {@code hash(String.class, String.class, Person.class)}. + * If you want to use a hash of {@code <String -> Person>} stored using UUID identifier, you would use: + * {@code hash(UUID.class, String.class, Person.class)}. + * + * @param redisKeyType the class of the keys + * @param fieldType the class of the fields + * @param valueType the class of the values + * @param the type of the redis key + * @param the type of the fields (map's keys) + * @param the type of the value + * @return the object to execute commands manipulating hashes (a.k.a. {@code Map<K, V>}). + */ + ReactiveHashCommands hash(TypeReference redisKeyType, TypeReference fieldType, + TypeReference valueType); + /** * Gets the object to execute commands manipulating hashes (a.k.a. {@code Map<String, V>}). *

@@ -178,6 +201,19 @@ default ReactiveHashCommands hash(Class typeOfValue) { return hash(String.class, String.class, typeOfValue); } + /** + * Gets the object to execute commands manipulating hashes (a.k.a. {@code Map<String, V>}). + *

+ * This is a shortcut on {@code hash(String.class, String.class, V)} + * + * @param typeOfValue the class of the values + * @param the type of the value + * @return the object to execute commands manipulating hashes (a.k.a. {@code Map<String, V>}). + */ + default ReactiveHashCommands hash(TypeReference typeOfValue) { + return hash(STRING_TYPE_REFERENCE, STRING_TYPE_REFERENCE, typeOfValue); + } + /** * Gets the object to execute commands manipulating geo items (a.k.a. {@code {longitude, latitude, member}}). *

@@ -191,6 +227,19 @@ default ReactiveHashCommands hash(Class typeOfValue) { */ ReactiveGeoCommands geo(Class redisKeyType, Class memberType); + /** + * Gets the object to execute commands manipulating geo items (a.k.a. {@code {longitude, latitude, member}}). + *

+ * {@code V} represents the type of the member, i.e. the localized thing. + * + * @param redisKeyType the class of the keys + * @param memberType the class of the members + * @param the type of the redis key + * @param the type of the member + * @return the object to execute geo commands. + */ + ReactiveGeoCommands geo(TypeReference redisKeyType, TypeReference memberType); + /** * Gets the object to execute commands manipulating geo items (a.k.a. {@code {longitude, latitude, member}}). *

@@ -204,6 +253,19 @@ default ReactiveGeoCommands geo(Class memberType) { return geo(String.class, memberType); } + /** + * Gets the object to execute commands manipulating geo items (a.k.a. {@code {longitude, latitude, member}}). + *

+ * {@code V} represents the type of the member, i.e. the localized thing. + * + * @param memberType the class of the members + * @param the type of the member + * @return the object to execute geo commands. + */ + default ReactiveGeoCommands geo(TypeReference memberType) { + return geo(STRING_TYPE_REFERENCE, memberType); + } + /** * Gets the object to execute commands manipulating keys and expiration times. * @@ -213,6 +275,15 @@ default ReactiveGeoCommands geo(Class memberType) { */ ReactiveKeyCommands key(Class redisKeyType); + /** + * Gets the object to execute commands manipulating keys and expiration times. + * + * @param redisKeyType the type of the keys + * @param the type of the key + * @return the object to execute commands manipulating keys. + */ + ReactiveKeyCommands key(TypeReference redisKeyType); + /** * Gets the object to execute commands manipulating keys and expiration times. * @@ -233,6 +304,17 @@ default ReactiveKeyCommands key() { */ ReactiveSortedSetCommands sortedSet(Class redisKeyType, Class valueType); + /** + * Gets the object to execute commands manipulating sorted sets. + * + * @param redisKeyType the type of the keys + * @param valueType the type of the value sorted in the sorted sets + * @param the type of the key + * @param the type of the value + * @return the object to manipulate sorted sets. + */ + ReactiveSortedSetCommands sortedSet(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to execute commands manipulating sorted sets. * @@ -244,6 +326,17 @@ default ReactiveSortedSetCommands sortedSet(Class valueType) { return sortedSet(String.class, valueType); } + /** + * Gets the object to execute commands manipulating sorted sets. + * + * @param valueType the type of the value sorted in the sorted sets + * @param the type of the value + * @return the object to manipulate sorted sets. + */ + default ReactiveSortedSetCommands sortedSet(TypeReference valueType) { + return sortedSet(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to execute commands manipulating stored strings. *

@@ -258,6 +351,20 @@ default ReactiveSortedSetCommands sortedSet(Class valueType) { */ ReactiveValueCommands value(Class redisKeyType, Class valueType); + /** + * Gets the object to execute commands manipulating stored strings. + *

+ * NOTE: Instead of {@code string}, this group is named {@code value} to avoid the confusion with the + * Java String type. Indeed, Redis strings can be strings, numbers, byte arrays... + * + * @param redisKeyType the type of the keys + * @param valueType the type of the value, often String, or the value are encoded/decoded using codecs. + * @param the type of the key + * @param the type of the value + * @return the object to manipulate stored strings. + */ + ReactiveValueCommands value(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to execute commands manipulating stored strings. *

@@ -272,6 +379,20 @@ default ReactiveValueCommands value(Class valueType) { return value(String.class, valueType); } + /** + * Gets the object to execute commands manipulating stored strings. + *

+ * NOTE: Instead of {@code string}, this group is named {@code value} to avoid the confusion with the + * Java String type. Indeed, Redis strings can be strings, numbers, byte arrays... + * + * @param valueType the type of the value, often String, or the value are encoded/decoded using codecs. + * @param the type of the value + * @return the object to manipulate stored strings. + */ + default ReactiveValueCommands value(TypeReference valueType) { + return value(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to execute commands manipulating stored strings. * @@ -309,6 +430,17 @@ default ReactiveStringCommands string(Class valueType) { */ ReactiveSetCommands set(Class redisKeyType, Class memberType); + /** + * Gets the object to execute commands manipulating sets. + * + * @param redisKeyType the type of the keys + * @param memberType the type of the member stored in each set + * @param the type of the key + * @param the type of the member + * @return the object to manipulate sets. + */ + ReactiveSetCommands set(TypeReference redisKeyType, TypeReference memberType); + /** * Gets the object to execute commands manipulating sets. * @@ -320,6 +452,17 @@ default ReactiveSetCommands set(Class memberType) { return set(String.class, memberType); } + /** + * Gets the object to execute commands manipulating sets. + * + * @param memberType the type of the member stored in each set + * @param the type of the member + * @return the object to manipulate sets. + */ + default ReactiveSetCommands set(TypeReference memberType) { + return set(STRING_TYPE_REFERENCE, memberType); + } + /** * Gets the object to execute commands manipulating lists. * @@ -342,6 +485,28 @@ default ReactiveListCommands list(Class memberType) { return list(String.class, memberType); } + /** + * Gets the object to execute commands manipulating lists. + * + * @param redisKeyType the type of the keys + * @param memberType the type of the member stored in each list + * @param the type of the key + * @param the type of the member + * @return the object to manipulate sets. + */ + ReactiveListCommands list(TypeReference redisKeyType, TypeReference memberType); + + /** + * Gets the object to execute commands manipulating lists. + * + * @param memberType the type of the member stored in each list + * @param the type of the member + * @return the object to manipulate sets. + */ + default ReactiveListCommands list(TypeReference memberType) { + return list(STRING_TYPE_REFERENCE, memberType); + } + /** * Gets the object to execute commands manipulating hyperloglog data structures. * @@ -353,6 +518,17 @@ default ReactiveListCommands list(Class memberType) { */ ReactiveHyperLogLogCommands hyperloglog(Class redisKeyType, Class memberType); + /** + * Gets the object to execute commands manipulating hyperloglog data structures. + * + * @param redisKeyType the type of the keys + * @param memberType the type of the member stored in the data structure + * @param the type of the key + * @param the type of the member + * @return the object to manipulate hyper log log data structures. + */ + ReactiveHyperLogLogCommands hyperloglog(TypeReference redisKeyType, TypeReference memberType); + /** * Gets the object to execute commands manipulating hyperloglog data structures. * @@ -364,6 +540,17 @@ default ReactiveHyperLogLogCommands hyperloglog(Class memberTy return hyperloglog(String.class, memberType); } + /** + * Gets the object to execute commands manipulating hyperloglog data structures. + * + * @param memberType the type of the member stored in the data structure + * @param the type of the member + * @return the object to manipulate hyper log log data structures. + */ + default ReactiveHyperLogLogCommands hyperloglog(TypeReference memberType) { + return hyperloglog(STRING_TYPE_REFERENCE, memberType); + } + /** * Gets the object to execute commands manipulating bitmap data structures. * @@ -373,6 +560,15 @@ default ReactiveHyperLogLogCommands hyperloglog(Class memberTy */ ReactiveBitMapCommands bitmap(Class redisKeyType); + /** + * Gets the object to execute commands manipulating bitmap data structures. + * + * @param redisKeyType the type of the keys + * @param the type of the key + * @return the object to manipulate bitmap data structures. + */ + ReactiveBitMapCommands bitmap(TypeReference redisKeyType); + /** * Gets the object to execute commands manipulating bitmap data structures. * @@ -395,6 +591,20 @@ default ReactiveBitMapCommands bitmap() { */ ReactiveStreamCommands stream(Class redisKeyType, Class fieldType, Class valueType); + /** + * Gets the object to execute commands manipulating streams. + * + * @param redisKeyType the class of the keys + * @param fieldType the class of the fields included in the message exchanged on the streams + * @param valueType the class of the values included in the message exchanged on the streams + * @param the type of the redis key + * @param the type of the fields (map's keys) + * @param the type of the value + * @return the object to execute commands manipulating streams. + */ + ReactiveStreamCommands stream(TypeReference redisKeyType, TypeReference fieldType, + TypeReference valueType); + /** * Gets the object to execute commands manipulating streams, using a string key, and string fields. * @@ -405,6 +615,16 @@ default ReactiveStreamCommands stream(Class typeOfValu return stream(String.class, String.class, typeOfValue); } + /** + * Gets the object to execute commands manipulating streams, using a string key, and string fields. + * + * @param the type of the value + * @return the object to execute commands manipulating streams. + */ + default ReactiveStreamCommands stream(TypeReference typeOfValue) { + return stream(STRING_TYPE_REFERENCE, STRING_TYPE_REFERENCE, typeOfValue); + } + /** * Gets the object to publish and receive messages. * @@ -414,6 +634,15 @@ default ReactiveStreamCommands stream(Class typeOfValu */ ReactivePubSubCommands pubsub(Class messageType); + /** + * Gets the object to publish and receive messages. + * + * @param messageType the type of message + * @param the type of message + * @return the object to publish and subscribe to Redis channels + */ + ReactivePubSubCommands pubsub(TypeReference messageType); + /** * Gets the object to manipulate JSON values. * This group requires the RedisJSON module. @@ -433,6 +662,15 @@ default ReactiveJsonCommands json() { */ ReactiveJsonCommands json(Class redisKeyType); + /** + * Gets the object to manipulate JSON values. + * This group requires the RedisJSON module. + * + * @param the type of keys + * @return the object to manipulate JSON values. + */ + ReactiveJsonCommands json(TypeReference redisKeyType); + /** * Gets the object to manipulate Bloom filters. * This group requires the RedisBloom module. @@ -444,6 +682,17 @@ default ReactiveBloomCommands bloom(Class valueType) { return bloom(String.class, valueType); } + /** + * Gets the object to manipulate Bloom filters. + * This group requires the RedisBloom module. + * + * @param the type of the values added into the Bloom filter + * @return the object to manipulate bloom values. + */ + default ReactiveBloomCommands bloom(TypeReference valueType) { + return bloom(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to manipulate Bloom filters. * This group requires the RedisBloom module. @@ -454,6 +703,16 @@ default ReactiveBloomCommands bloom(Class valueType) { */ ReactiveBloomCommands bloom(Class redisKeyType, Class valueType); + /** + * Gets the object to manipulate Bloom filters. + * This group requires the RedisBloom module. + * + * @param the type of keys + * @param the type of the values added into the Bloom filter + * @return the object to manipulate bloom values. + */ + ReactiveBloomCommands bloom(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to manipulate Cuckoo filters. * This group requires the RedisBloom module (including the Cuckoo @@ -466,6 +725,18 @@ default ReactiveCuckooCommands cuckoo(Class valueType) { return cuckoo(String.class, valueType); } + /** + * Gets the object to manipulate Cuckoo filters. + * This group requires the RedisBloom module (including the Cuckoo + * filter support). + * + * @param the type of the values added into the Cuckoo filter + * @return the object to manipulate Cuckoo values. + */ + default ReactiveCuckooCommands cuckoo(TypeReference valueType) { + return cuckoo(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to manipulate Cuckoo filters. * This group requires the RedisBloom module (including the Cuckoo @@ -477,6 +748,17 @@ default ReactiveCuckooCommands cuckoo(Class valueType) { */ ReactiveCuckooCommands cuckoo(Class redisKeyType, Class valueType); + /** + * Gets the object to manipulate Cuckoo filters. + * This group requires the RedisBloom module (including the Cuckoo + * filter support). + * + * @param the type of keys + * @param the type of the values added into the Cuckoo filter + * @return the object to manipulate Cuckoo values. + */ + ReactiveCuckooCommands cuckoo(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to manipulate Count-Min sketches. * This group requires the RedisBloom module (including the count-min @@ -489,6 +771,18 @@ default ReactiveCountMinCommands countmin(Class valueType) { return countmin(String.class, valueType); } + /** + * Gets the object to manipulate Count-Min sketches. + * This group requires the RedisBloom module (including the count-min + * sketches support). + * + * @param the type of the values added into the count-min sketches + * @return the object to manipulate count-min sketches. + */ + default ReactiveCountMinCommands countmin(TypeReference valueType) { + return countmin(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to manipulate Count-Min sketches. * This group requires the RedisBloom module (including the count-min @@ -500,6 +794,17 @@ default ReactiveCountMinCommands countmin(Class valueType) { */ ReactiveCountMinCommands countmin(Class redisKeyType, Class valueType); + /** + * Gets the object to manipulate Count-Min sketches. + * This group requires the RedisBloom module (including the count-min + * sketches support). + * + * @param the type of keys + * @param the type of the values added into the count-min sketches + * @return the object to manipulate count-min sketches. + */ + ReactiveCountMinCommands countmin(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to manipulate Top-K list. * This group requires the RedisBloom module (including the top-k @@ -512,6 +817,18 @@ default ReactiveTopKCommands topk(Class valueType) { return topk(String.class, valueType); } + /** + * Gets the object to manipulate Top-K list. + * This group requires the RedisBloom module (including the top-k + * list support). + * + * @param the type of the values added into the top-k lists + * @return the object to manipulate top-k lists. + */ + default ReactiveTopKCommands topk(TypeReference valueType) { + return topk(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to manipulate Top-K list. * This group requires the RedisBloom module (including the top-k @@ -523,6 +840,17 @@ default ReactiveTopKCommands topk(Class valueType) { */ ReactiveTopKCommands topk(Class redisKeyType, Class valueType); + /** + * Gets the object to manipulate Top-K list. + * This group requires the RedisBloom module (including the top-k + * list support). + * + * @param the type of keys + * @param the type of the values added into the top-k lists + * @return the object to manipulate top-k lists. + */ + ReactiveTopKCommands topk(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to manipulate graphs. * This group requires the RedisGraph module. @@ -550,8 +878,10 @@ default ReactiveGraphCommands graph() { * * @param the type of keys * @return the object to search documents + * @deprecated Use the variant without parameter, as the index name must be a string. */ @Experimental("The Redis search support is experimental") + @Deprecated ReactiveSearchCommands search(Class redisKeyType); /** @@ -575,6 +905,16 @@ default ReactiveSearchCommands search() { @Experimental("The Redis auto-suggest support is experimental") ReactiveAutoSuggestCommands autosuggest(Class redisKeyType); + /** + * Gets the object to emit commands from the {@code auto-suggest} group. + * This group requires the RedisSearch module. + * + * @param the type of keys + * @return the object to get suggestions + */ + @Experimental("The Redis auto-suggest support is experimental") + ReactiveAutoSuggestCommands autosuggest(TypeReference redisKeyType); + /** * Gets the object to emit commands from the {@code auto-suggest} group. * This group requires the RedisSearch module. @@ -596,6 +936,16 @@ default ReactiveAutoSuggestCommands autosuggest() { @Experimental("The Redis time series support is experimental") ReactiveTimeSeriesCommands timeseries(Class redisKeyType); + /** + * Gets the object to emit commands from the {@code time series} group. + * This group requires the Redis Time Series module. + * + * @param the type of keys + * @return the object to manipulate time series + */ + @Experimental("The Redis time series support is experimental") + ReactiveTimeSeriesCommands timeseries(TypeReference redisKeyType); + /** * Gets the object to emit commands from the {@code time series} group. * This group requires the Redis Time Series module. diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/RedisDataSource.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/RedisDataSource.java index 52d9852a9b46c..3410684cf367f 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/RedisDataSource.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/RedisDataSource.java @@ -1,9 +1,13 @@ package io.quarkus.redis.datasource; +import static io.quarkus.redis.runtime.datasource.Marshaller.STRING_TYPE_REFERENCE; + import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.autosuggest.AutoSuggestCommands; import io.quarkus.redis.datasource.bitmap.BitMapCommands; import io.quarkus.redis.datasource.bloom.BloomCommands; @@ -161,6 +165,25 @@ OptimisticLockingTransactionResult withTransaction(Function HashCommands hash(Class redisKeyType, Class typeOfField, Class typeOfValue); + /** + * Gets the object to execute commands manipulating hashes (a.k.a. {@code Map<F, V>}). + *

+ * If you want to use a hash of {@code <String -> Person>} stored using String identifier, you would use: + * {@code hash(String.class, String.class, Person.class)}. + * If you want to use a hash of {@code <String -> Person>} stored using UUID identifier, you would use: + * {@code hash(UUID.class, String.class, Person.class)}. + * + * @param redisKeyType the class of the keys + * @param typeOfField the class of the fields + * @param typeOfValue the class of the values + * @param the type of the redis key + * @param the type of the fields (map's keys) + * @param the type of the value + * @return the object to execute commands manipulating hashes (a.k.a. {@code Map<K, V>}). + */ + HashCommands hash(TypeReference redisKeyType, TypeReference typeOfField, + TypeReference typeOfValue); + /** * Gets the object to execute commands manipulating hashes (a.k.a. {@code Map<String, V>}). *

@@ -174,6 +197,19 @@ default HashCommands hash(Class typeOfValue) { return hash(String.class, String.class, typeOfValue); } + /** + * Gets the object to execute commands manipulating hashes (a.k.a. {@code Map<String, V>}). + *

+ * This is a shortcut on {@code hash(String.class, String.class, V)} + * + * @param typeOfValue the class of the values + * @param the type of the value + * @return the object to execute commands manipulating hashes (a.k.a. {@code Map<String, V>}). + */ + default HashCommands hash(TypeReference typeOfValue) { + return hash(STRING_TYPE_REFERENCE, STRING_TYPE_REFERENCE, typeOfValue); + } + /** * Gets the object to execute commands manipulating geo items (a.k.a. {@code {longitude, latitude, member}}). *

@@ -187,6 +223,19 @@ default HashCommands hash(Class typeOfValue) { */ GeoCommands geo(Class redisKeyType, Class memberType); + /** + * Gets the object to execute commands manipulating geo items (a.k.a. {@code {longitude, latitude, member}}). + *

+ * {@code V} represents the type of the member, i.e. the localized thing. + * + * @param redisKeyType the class of the keys + * @param memberType the class of the members + * @param the type of the redis key + * @param the type of the member + * @return the object to execute geo commands. + */ + GeoCommands geo(TypeReference redisKeyType, TypeReference memberType); + /** * Gets the object to execute commands manipulating geo items (a.k.a. {@code {longitude, latitude, member}}). *

@@ -200,6 +249,19 @@ default GeoCommands geo(Class memberType) { return geo(String.class, memberType); } + /** + * Gets the object to execute commands manipulating geo items (a.k.a. {@code {longitude, latitude, member}}). + *

+ * {@code V} represents the type of the member, i.e. the localized thing. + * + * @param memberType the class of the members + * @param the type of the member + * @return the object to execute geo commands. + */ + default GeoCommands geo(TypeReference memberType) { + return geo(STRING_TYPE_REFERENCE, memberType); + } + /** * Gets the object to execute commands manipulating keys and expiration times. * @@ -209,6 +271,15 @@ default GeoCommands geo(Class memberType) { */ KeyCommands key(Class redisKeyType); + /** + * Gets the object to execute commands manipulating keys and expiration times. + * + * @param redisKeyType the type of the keys + * @param the type of the key + * @return the object to execute commands manipulating keys. + */ + KeyCommands key(TypeReference redisKeyType); + /** * Gets the object to execute commands manipulating keys and expiration times. * @@ -229,6 +300,17 @@ default KeyCommands key() { */ SortedSetCommands sortedSet(Class redisKeyType, Class valueType); + /** + * Gets the object to execute commands manipulating sorted sets. + * + * @param redisKeyType the type of the keys + * @param valueType the type of the value sorted in the sorted sets + * @param the type of the key + * @param the type of the value + * @return the object to manipulate sorted sets. + */ + SortedSetCommands sortedSet(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to execute commands manipulating sorted sets. * @@ -240,6 +322,17 @@ default SortedSetCommands sortedSet(Class valueType) { return sortedSet(String.class, valueType); } + /** + * Gets the object to execute commands manipulating sorted sets. + * + * @param valueType the type of the value sorted in the sorted sets + * @param the type of the value + * @return the object to manipulate sorted sets. + */ + default SortedSetCommands sortedSet(TypeReference valueType) { + return sortedSet(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to execute commands manipulating stored strings. * @@ -255,6 +348,21 @@ default SortedSetCommands sortedSet(Class valueType) { */ ValueCommands value(Class redisKeyType, Class valueType); + /** + * Gets the object to execute commands manipulating stored strings. + * + *

+ * NOTE: Instead of {@code string}, this group is named {@code value} to avoid the confusion with the + * Java String type. Indeed, Redis strings can be strings, numbers, byte arrays... + * + * @param redisKeyType the type of the keys + * @param valueType the type of the value, often String, or the value are encoded/decoded using codecs. + * @param the type of the key + * @param the type of the value + * @return the object to manipulate stored strings. + */ + ValueCommands value(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to execute commands manipulating stored strings. * @@ -270,6 +378,21 @@ default ValueCommands value(Class valueType) { return value(String.class, valueType); } + /** + * Gets the object to execute commands manipulating stored strings. + * + *

+ * NOTE: Instead of {@code string}, this group is named {@code value} to avoid the confusion with the + * Java String type. Indeed, Redis strings can be strings, numbers, byte arrays... + * + * @param valueType the type of the value, often String, or the value are encoded/decoded using codecs. + * @param the type of the value + * @return the object to manipulate stored strings. + */ + default ValueCommands value(TypeReference valueType) { + return value(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to execute commands manipulating stored strings. * @@ -307,6 +430,17 @@ default StringCommands string(Class valueType) { */ SetCommands set(Class redisKeyType, Class memberType); + /** + * Gets the object to execute commands manipulating sets. + * + * @param redisKeyType the type of the keys + * @param memberType the type of the member stored in each set + * @param the type of the key + * @param the type of the member + * @return the object to manipulate sets. + */ + SetCommands set(TypeReference redisKeyType, TypeReference memberType); + /** * Gets the object to execute commands manipulating sets. * @@ -318,6 +452,17 @@ default SetCommands set(Class memberType) { return set(String.class, memberType); } + /** + * Gets the object to execute commands manipulating sets. + * + * @param memberType the type of the member stored in each set + * @param the type of the member + * @return the object to manipulate sets. + */ + default SetCommands set(TypeReference memberType) { + return set(STRING_TYPE_REFERENCE, memberType); + } + /** * Gets the object to execute commands manipulating lists. * @@ -340,6 +485,28 @@ default ListCommands list(Class memberType) { return list(String.class, memberType); } + /** + * Gets the object to execute commands manipulating lists. + * + * @param redisKeyType the type of the keys + * @param memberType the type of the member stored in each list + * @param the type of the key + * @param the type of the member + * @return the object to manipulate sets. + */ + ListCommands list(TypeReference redisKeyType, TypeReference memberType); + + /** + * Gets the object to execute commands manipulating lists. + * + * @param memberType the type of the member stored in each list + * @param the type of the member + * @return the object to manipulate sets. + */ + default ListCommands list(TypeReference memberType) { + return list(STRING_TYPE_REFERENCE, memberType); + } + /** * Gets the object to execute commands manipulating hyperloglog data structures. * @@ -351,6 +518,17 @@ default ListCommands list(Class memberType) { */ HyperLogLogCommands hyperloglog(Class redisKeyType, Class memberType); + /** + * Gets the object to execute commands manipulating hyperloglog data structures. + * + * @param redisKeyType the type of the keys + * @param memberType the type of the member stored in the data structure + * @param the type of the key + * @param the type of the member + * @return the object to manipulate hyper log log data structures. + */ + HyperLogLogCommands hyperloglog(TypeReference redisKeyType, TypeReference memberType); + /** * Gets the object to execute commands manipulating hyperloglog data structures. * @@ -362,6 +540,17 @@ default HyperLogLogCommands hyperloglog(Class memberType) { return hyperloglog(String.class, memberType); } + /** + * Gets the object to execute commands manipulating hyperloglog data structures. + * + * @param memberType the type of the member stored in the data structure + * @param the type of the member + * @return the object to manipulate hyper log log data structures. + */ + default HyperLogLogCommands hyperloglog(TypeReference memberType) { + return hyperloglog(STRING_TYPE_REFERENCE, memberType); + } + /** * Gets the object to execute commands manipulating bitmap data structures. * @@ -371,6 +560,15 @@ default HyperLogLogCommands hyperloglog(Class memberType) { */ BitMapCommands bitmap(Class redisKeyType); + /** + * Gets the object to execute commands manipulating bitmap data structures. + * + * @param redisKeyType the type of the keys + * @param the type of the key + * @return the object to manipulate bitmap data structures. + */ + BitMapCommands bitmap(TypeReference redisKeyType); + /** * Gets the object to execute commands manipulating bitmap data structures. * @@ -393,6 +591,20 @@ default BitMapCommands bitmap() { */ StreamCommands stream(Class redisKeyType, Class fieldType, Class valueType); + /** + * Gets the object to execute commands manipulating streams. + * + * @param redisKeyType the class of the keys + * @param fieldType the class of the fields included in the message exchanged on the streams + * @param valueType the class of the values included in the message exchanged on the streams + * @param the type of the redis key + * @param the type of the fields (map's keys) + * @param the type of the value + * @return the object to execute commands manipulating streams. + */ + StreamCommands stream(TypeReference redisKeyType, TypeReference fieldType, + TypeReference valueType); + /** * Gets the object to execute commands manipulating streams, using a string key, and string fields. * @@ -403,6 +615,16 @@ default StreamCommands stream(Class typeOfValue) { return stream(String.class, String.class, typeOfValue); } + /** + * Gets the object to execute commands manipulating streams, using a string key, and string fields. + * + * @param the type of the value + * @return the object to execute commands manipulating streams. + */ + default StreamCommands stream(TypeReference typeOfValue) { + return stream(STRING_TYPE_REFERENCE, STRING_TYPE_REFERENCE, typeOfValue); + } + /** * Gets the object to manipulate JSON values. * This group requires the RedisJSON module. @@ -422,6 +644,15 @@ default JsonCommands json() { */ JsonCommands json(Class redisKeyType); + /** + * Gets the object to manipulate JSON values. + * This group requires the RedisJSON module. + * + * @param the type of keys + * @return the object to manipulate JSON values. + */ + JsonCommands json(TypeReference redisKeyType); + /** * Gets the object to manipulate Bloom filters. * This group requires the RedisBloom module. @@ -433,6 +664,17 @@ default BloomCommands bloom(Class valueType) { return bloom(String.class, valueType); } + /** + * Gets the object to manipulate Bloom filters. + * This group requires the RedisBloom module. + * + * @param the type of the values added into the Bloom filter + * @return the object to manipulate bloom filters. + */ + default BloomCommands bloom(TypeReference valueType) { + return bloom(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to manipulate Bloom filters. * This group requires the RedisBloom module. @@ -443,6 +685,16 @@ default BloomCommands bloom(Class valueType) { */ BloomCommands bloom(Class redisKeyType, Class valueType); + /** + * Gets the object to manipulate Bloom filters. + * This group requires the RedisBloom module. + * + * @param the type of keys + * @param the type of the values added into the Bloom filter + * @return the object to manipulate bloom filters. + */ + BloomCommands bloom(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to manipulate Cuckoo filters. * This group requires the RedisBloom module (including the Cuckoo @@ -455,6 +707,18 @@ default CuckooCommands cuckoo(Class valueType) { return cuckoo(String.class, valueType); } + /** + * Gets the object to manipulate Cuckoo filters. + * This group requires the RedisBloom module (including the Cuckoo + * filter support). + * + * @param the type of the values added into the Cuckoo filter + * @return the object to manipulate Cuckoo filters. + */ + default CuckooCommands cuckoo(TypeReference valueType) { + return cuckoo(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to manipulate Cuckoo filters. * This group requires the RedisBloom module (including the Cuckoo @@ -466,6 +730,17 @@ default CuckooCommands cuckoo(Class valueType) { */ CuckooCommands cuckoo(Class redisKeyType, Class valueType); + /** + * Gets the object to manipulate Cuckoo filters. + * This group requires the RedisBloom module (including the Cuckoo + * filter support). + * + * @param the type of keys + * @param the type of the values added into the Cuckoo filter + * @return the object to manipulate Cuckoo filters. + */ + CuckooCommands cuckoo(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to manipulate Count-Min sketches. * This group requires the RedisBloom module (including the count-min @@ -478,6 +753,18 @@ default CountMinCommands countmin(Class valueType) { return countmin(String.class, valueType); } + /** + * Gets the object to manipulate Count-Min sketches. + * This group requires the RedisBloom module (including the count-min + * sketches support). + * + * @param the type of the values added into the count-min sketches + * @return the object to manipulate count-min sketches. + */ + default CountMinCommands countmin(TypeReference valueType) { + return countmin(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to manipulate Count-Min sketches. * This group requires the RedisBloom module (including the count-min @@ -489,6 +776,17 @@ default CountMinCommands countmin(Class valueType) { */ CountMinCommands countmin(Class redisKeyType, Class valueType); + /** + * Gets the object to manipulate Count-Min sketches. + * This group requires the RedisBloom module (including the count-min + * sketches support). + * + * @param the type of keys + * @param the type of the values added into the count-min sketches + * @return the object to manipulate count-min sketches. + */ + CountMinCommands countmin(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to manipulate Top-K list. * This group requires the RedisBloom module (including the top-k @@ -501,6 +799,18 @@ default TopKCommands topk(Class valueType) { return topk(String.class, valueType); } + /** + * Gets the object to manipulate Top-K list. + * This group requires the RedisBloom module (including the top-k + * list support). + * + * @param the type of the values added into the top-k lists + * @return the object to manipulate top-k lists. + */ + default TopKCommands topk(TypeReference valueType) { + return topk(STRING_TYPE_REFERENCE, valueType); + } + /** * Gets the object to manipulate Top-K list. * This group requires the RedisBloom module (including the top-k @@ -512,13 +822,24 @@ default TopKCommands topk(Class valueType) { */ TopKCommands topk(Class redisKeyType, Class valueType); + /** + * Gets the object to manipulate Top-K list. + * This group requires the RedisBloom module (including the top-k + * list support). + * + * @param the type of keys + * @param the type of the values added into the top-k lists + * @return the object to manipulate top-k lists. + */ + TopKCommands topk(TypeReference redisKeyType, TypeReference valueType); + /** * Gets the object to manipulate graphs. * This group requires the RedisGraph module. * * @return the object to manipulate graphs. */ - @Experimental("The Redis graph support is experimental") + @Experimental("The Redis graph support is experimental, in addition, the graph module EOL") default GraphCommands graph() { return graph(String.class); } @@ -530,7 +851,7 @@ default GraphCommands graph() { * @param the type of keys * @return the object to manipulate graphs lists. */ - @Experimental("The Redis graph support is experimental") + @Experimental("The Redis graph support is experimental, in addition, the graph module EOL") GraphCommands graph(Class redisKeyType); /** @@ -539,8 +860,10 @@ default GraphCommands graph() { * * @param the type of keys * @return the object to search documents + * @deprecated Use the variant without parameter, as the index name must be a string */ @Experimental("The Redis search support is experimental") + @Deprecated SearchCommands search(Class redisKeyType); /** @@ -564,6 +887,16 @@ default SearchCommands search() { @Experimental("The Redis auto-suggest support is experimental") AutoSuggestCommands autosuggest(Class redisKeyType); + /** + * Gets the object to emit commands from the {@code auto-suggest} group. + * This group requires the RedisSearch module. + * + * @param the type of keys + * @return the object to get suggestions + */ + @Experimental("The Redis auto-suggest support is experimental") + AutoSuggestCommands autosuggest(TypeReference redisKeyType); + /** * Gets the object to emit commands from the {@code auto-suggest} group. * This group requires the RedisSearch module. @@ -585,6 +918,16 @@ default AutoSuggestCommands autosuggest() { @Experimental("The Redis time series support is experimental") TimeSeriesCommands timeseries(Class redisKeyType); + /** + * Gets the object to emit commands from the {@code time series} group. + * This group requires the Redis Time Series module. + * + * @param the type of keys + * @return the object to manipulate time series + */ + @Experimental("The Redis time series support is experimental") + TimeSeriesCommands timeseries(TypeReference redisKeyType); + /** * Gets the object to emit commands from the {@code time series} group. * This group requires the Redis Time Series module. @@ -605,6 +948,15 @@ default TimeSeriesCommands timeseries() { */ PubSubCommands pubsub(Class messageType); + /** + * Gets the objects to publish and receive messages. + * + * @param messageType the type of message + * @param the type of message + * @return the object to publish and subscribe to Redis channels + */ + PubSubCommands pubsub(TypeReference messageType); + /** * Executes a command. * This method is used to execute commands not offered by the API. diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/codecs/Codecs.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/codecs/Codecs.java index f7fc7ceb4c764..765caeb025e88 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/codecs/Codecs.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/codecs/Codecs.java @@ -1,5 +1,6 @@ package io.quarkus.redis.datasource.codecs; +import java.io.IOException; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.util.List; @@ -7,8 +8,12 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Stream; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + import io.vertx.core.buffer.Buffer; import io.vertx.core.json.Json; +import io.vertx.core.json.jackson.DatabindCodec; public class Codecs { @@ -39,11 +44,24 @@ public static Codec getDefaultCodecFor(Type type) { } public static class JsonCodec implements Codec { - - private final Type clazz; + private final TypeReference type; + private final Class clazz; + private final ObjectMapper mapper; public JsonCodec(Type clazz) { - this.clazz = clazz; + if (clazz instanceof Class) { + this.clazz = (Class) clazz; + this.type = null; + } else { + this.type = new TypeReference<>() { + @Override + public Type getType() { + return clazz; + } + }; + this.clazz = null; + } + this.mapper = DatabindCodec.mapper(); } @Override @@ -58,8 +76,15 @@ public byte[] encode(Object item) { @Override public Object decode(byte[] payload) { - // TODO This would need to be revisited when we use TypeReference. - return Json.decodeValue(Buffer.buffer(payload), (Class) clazz); + try { + if (clazz != null) { + return Json.decodeValue(Buffer.buffer(payload), clazz); + } else { + return mapper.readValue(payload, type); + } + } catch (IOException e) { + throw new RuntimeException(e); + } } } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractAutoSuggestCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractAutoSuggestCommands.java index e0288d5ea3fe0..fed14ae090c17 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractAutoSuggestCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractAutoSuggestCommands.java @@ -3,6 +3,8 @@ import static io.quarkus.redis.runtime.datasource.Validation.notNullOrBlank; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; + import io.quarkus.redis.datasource.autosuggest.GetArgs; import io.smallrye.mutiny.Uni; import io.vertx.mutiny.redis.client.Command; @@ -10,7 +12,7 @@ public class AbstractAutoSuggestCommands extends AbstractRedisCommands { - AbstractAutoSuggestCommands(RedisCommandExecutor redis, Class k) { + AbstractAutoSuggestCommands(RedisCommandExecutor redis, Type k) { super(redis, new Marshaller(k)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractBitMapCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractBitMapCommands.java index c6026a568ba26..646985313f768 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractBitMapCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractBitMapCommands.java @@ -4,6 +4,7 @@ import static io.quarkus.redis.runtime.datasource.Validation.notNullOrEmpty; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.List; import io.quarkus.redis.datasource.bitmap.BitFieldArgs; @@ -13,7 +14,7 @@ class AbstractBitMapCommands extends AbstractRedisCommands { - AbstractBitMapCommands(RedisCommandExecutor redis, Class k) { + AbstractBitMapCommands(RedisCommandExecutor redis, Type k) { super(redis, new Marshaller(k)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractBloomCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractBloomCommands.java index c9107580eff3d..80376d0a74332 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractBloomCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractBloomCommands.java @@ -3,6 +3,8 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; + import io.quarkus.redis.datasource.bloom.BfInsertArgs; import io.quarkus.redis.datasource.bloom.BfReserveArgs; import io.smallrye.mutiny.Uni; @@ -11,7 +13,7 @@ class AbstractBloomCommands extends AbstractRedisCommands { - AbstractBloomCommands(RedisCommandExecutor redis, Class k, Class v) { + AbstractBloomCommands(RedisCommandExecutor redis, Type k, Type v) { super(redis, new Marshaller(k, v)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractCountMinCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractCountMinCommands.java index 474e433fac24a..1129eb275d246 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractCountMinCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractCountMinCommands.java @@ -4,6 +4,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.isNotEmpty; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.List; import java.util.Map; @@ -13,7 +14,7 @@ public class AbstractCountMinCommands extends AbstractRedisCommands { - AbstractCountMinCommands(RedisCommandExecutor redis, Class k, Class v) { + AbstractCountMinCommands(RedisCommandExecutor redis, Type k, Type v) { super(redis, new Marshaller(k, v)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractCuckooCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractCuckooCommands.java index 81a3435facc0f..030479e5e82e2 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractCuckooCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractCuckooCommands.java @@ -3,6 +3,8 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; + import io.quarkus.redis.datasource.cuckoo.CfInsertArgs; import io.quarkus.redis.datasource.cuckoo.CfReserveArgs; import io.smallrye.mutiny.Uni; @@ -11,7 +13,7 @@ public class AbstractCuckooCommands extends AbstractRedisCommands { - AbstractCuckooCommands(RedisCommandExecutor redis, Class k, Class v) { + AbstractCuckooCommands(RedisCommandExecutor redis, Type k, Type v) { super(redis, new Marshaller(k, v)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractGeoCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractGeoCommands.java index 47841954c31be..c9987c32544e8 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractGeoCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractGeoCommands.java @@ -7,6 +7,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.OptionalDouble; @@ -31,13 +32,13 @@ class AbstractGeoCommands extends AbstractRedisCommands { - protected final Class typeOfValue; + protected final Type typeOfValue; protected final Codec keyCodec; protected final Codec valueCodec; private static final Pattern NOISE_REMOVER_PATTERN = Pattern.compile("[^a-zA-Z0-9\\.]"); - AbstractGeoCommands(RedisCommandExecutor redis, Class k, Class v) { + AbstractGeoCommands(RedisCommandExecutor redis, Type k, Type v) { super(redis, new Marshaller(k, v)); this.typeOfValue = v; this.keyCodec = Codecs.getDefaultCodecFor(k); diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractGraphCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractGraphCommands.java index 40281d977eaa8..36d484edf7f36 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractGraphCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractGraphCommands.java @@ -2,6 +2,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.time.Duration; import io.smallrye.mutiny.Uni; @@ -10,7 +11,7 @@ public class AbstractGraphCommands extends AbstractRedisCommands { - AbstractGraphCommands(RedisCommandExecutor redis, Class k) { + AbstractGraphCommands(RedisCommandExecutor redis, Type k) { super(redis, new Marshaller(k)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractHashCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractHashCommands.java index b656d42ec280b..f6acc5437ed6a 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractHashCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractHashCommands.java @@ -5,6 +5,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -16,10 +17,10 @@ class AbstractHashCommands extends AbstractRedisCommands { - protected final Class typeOfValue; - protected final Class typeOfField; + protected final Type typeOfValue; + protected final Type typeOfField; - AbstractHashCommands(RedisCommandExecutor redis, Class k, Class f, Class v) { + AbstractHashCommands(RedisCommandExecutor redis, Type k, Type f, Type v) { super(redis, new Marshaller(k, f, v)); this.typeOfField = f; this.typeOfValue = v; diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractHyperLogLogCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractHyperLogLogCommands.java index a60ee76644f7b..11b9a6720e5d2 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractHyperLogLogCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractHyperLogLogCommands.java @@ -4,13 +4,15 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; + import io.smallrye.mutiny.Uni; import io.vertx.mutiny.redis.client.Command; import io.vertx.mutiny.redis.client.Response; class AbstractHyperLogLogCommands extends AbstractRedisCommands { - AbstractHyperLogLogCommands(RedisCommandExecutor api, Class k, Class v) { + AbstractHyperLogLogCommands(RedisCommandExecutor api, Type k, Type v) { super(api, new Marshaller(k, v)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractJsonCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractJsonCommands.java index a2a31ead49674..8381d205b7ef1 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractJsonCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractJsonCommands.java @@ -4,6 +4,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -18,7 +19,7 @@ public class AbstractJsonCommands extends AbstractRedisCommands { private static final JsonSetArgs JSON_SET_DEFAULT = new JsonSetArgs(); - public AbstractJsonCommands(RedisCommandExecutor api, Class k) { + public AbstractJsonCommands(RedisCommandExecutor api, Type k) { super(api, new Marshaller(k)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractKeyCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractKeyCommands.java index f11a9c142ceba..dc7762bf71996 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractKeyCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractKeyCommands.java @@ -8,6 +8,7 @@ import static io.vertx.mutiny.redis.client.Command.EXPIRETIME; import static io.vertx.mutiny.redis.client.Command.PEXPIRETIME; +import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.Instant; @@ -24,9 +25,9 @@ class AbstractKeyCommands extends AbstractRedisCommands { - protected final Class typeOfKey; + protected final Type typeOfKey; - AbstractKeyCommands(RedisCommandExecutor redis, Class k) { + AbstractKeyCommands(RedisCommandExecutor redis, Type k) { super(redis, new Marshaller(k)); this.typeOfKey = k; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractListCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractListCommands.java index 66d25a6370237..51aa71db4f0b0 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractListCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractListCommands.java @@ -6,6 +6,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.positive; import static io.smallrye.mutiny.helpers.ParameterValidation.validate; +import java.lang.reflect.Type; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; @@ -20,15 +21,15 @@ class AbstractListCommands extends ReactiveSortable { - protected final Class typeOfValue; - protected final Class typeOfKey; + protected final Type typeOfValue; + protected final Type typeOfKey; protected static final LPosArgs DEFAULT_INSTANCE = new LPosArgs(); public static final Command LMPOP = Command.create("lmpop"); public static final Command BLMPOP = Command.create("blmpop"); - AbstractListCommands(RedisCommandExecutor redis, Class k, Class v) { + AbstractListCommands(RedisCommandExecutor redis, Type k, Type v) { super(redis, new Marshaller(k, v), v); this.typeOfKey = k; this.typeOfValue = v; diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSearchCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSearchCommands.java index d4b7792a89ed8..7d314c9f148a9 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSearchCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSearchCommands.java @@ -7,6 +7,8 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.positive; import static io.smallrye.mutiny.helpers.ParameterValidation.positiveOrZero; +import java.lang.reflect.Type; + import io.quarkus.redis.datasource.search.AggregateArgs; import io.quarkus.redis.datasource.search.CreateArgs; import io.quarkus.redis.datasource.search.IndexedField; @@ -18,7 +20,7 @@ public class AbstractSearchCommands extends AbstractRedisCommands { - AbstractSearchCommands(RedisCommandExecutor redis, Class k) { + AbstractSearchCommands(RedisCommandExecutor redis, Type k) { super(redis, new Marshaller(k)); } @@ -84,10 +86,6 @@ Uni _ftAlter(String index, IndexedField field, boolean skipInitialScan return execute(cmd); } - Uni _ftAlter(String index, IndexedField field) { - return _ftAlter(index, field, false); - } - Uni _ftCreate(String index, CreateArgs args) { notNullOrBlank(index, "index"); nonNull(args, "args"); diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSetCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSetCommands.java index 799ac49ef64ff..6ab4e7a52b845 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSetCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSetCommands.java @@ -5,6 +5,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; import static io.smallrye.mutiny.helpers.ParameterValidation.positive; +import java.lang.reflect.Type; import java.util.List; import java.util.Set; @@ -14,11 +15,11 @@ class AbstractSetCommands extends ReactiveSortable { - protected final Class typeOfValue; + protected final Type typeOfValue; public static final Command SINTERCARD = Command.create("sintercard"); - AbstractSetCommands(RedisCommandExecutor redis, Class k, Class v) { + AbstractSetCommands(RedisCommandExecutor redis, Type k, Type v) { super(redis, new Marshaller(k, v), v); this.typeOfValue = v; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSortedSetCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSortedSetCommands.java index 9d74dc8722e87..ee014247dd5e0 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSortedSetCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractSortedSetCommands.java @@ -9,6 +9,7 @@ import static java.lang.Double.NEGATIVE_INFINITY; import static java.lang.Double.POSITIVE_INFINITY; +import java.lang.reflect.Type; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; @@ -32,8 +33,8 @@ class AbstractSortedSetCommands extends ReactiveSortable { - protected final Class typeOfValue; - protected final Class typeOfKey; + protected final Type typeOfValue; + protected final Type typeOfKey; protected static final ZAggregateArgs DEFAULT_INSTANCE_AGG = new ZAggregateArgs(); protected static final ZRangeArgs DEFAULT_INSTANCE_RANGE = new ZRangeArgs(); @@ -42,7 +43,7 @@ class AbstractSortedSetCommands extends ReactiveSortable { public static final Command ZMPOP = Command.create("zmpop"); public static final Command BZMPOP = Command.create("bzmpop"); - AbstractSortedSetCommands(RedisCommandExecutor redis, Class k, Class v) { + AbstractSortedSetCommands(RedisCommandExecutor redis, Type k, Type v) { super(redis, new Marshaller(k, v), v); this.typeOfValue = v; this.typeOfKey = k; diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractStreamCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractStreamCommands.java index cd2a788c5d3e1..fa091c77ead49 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractStreamCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractStreamCommands.java @@ -6,6 +6,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -27,7 +28,7 @@ public class AbstractStreamCommands extends AbstractRedisCommands { - AbstractStreamCommands(RedisCommandExecutor redis, Class k, Class m, Class v) { + AbstractStreamCommands(RedisCommandExecutor redis, Type k, Type m, Type v) { super(redis, new Marshaller(k, m, v)); } @@ -318,7 +319,7 @@ Uni _xread(Map lastIdsPerStream, XReadArgs args) { return execute(cmd); } - private void writeStreamsAndIds(Map lastIdsPerStream, RedisCommand cmd) { + private void writeStreamsAndIds(Map lastIdsPerStream, RedisCommand cmd) { List ids = new ArrayList<>(); for (Map.Entry entry : lastIdsPerStream.entrySet()) { cmd.put(marshaller.encode(entry.getKey())); diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractStringCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractStringCommands.java index de857f54c512d..fd741433e0156 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractStringCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractStringCommands.java @@ -6,6 +6,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.positive; import static io.smallrye.mutiny.helpers.ParameterValidation.positiveOrZero; +import java.lang.reflect.Type; import java.util.Map; import io.quarkus.redis.datasource.string.GetExArgs; @@ -16,11 +17,11 @@ class AbstractStringCommands extends AbstractRedisCommands { - protected final Class typeOfValue; + protected final Type typeOfValue; public static final Command LCS = Command.create("lcs"); - AbstractStringCommands(RedisCommandExecutor redis, Class k, Class v) { + AbstractStringCommands(RedisCommandExecutor redis, Type k, Type v) { super(redis, new Marshaller(k, v)); this.typeOfValue = v; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractTimeSeriesCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractTimeSeriesCommands.java index 7657d25eb9e10..584ccfec0eefc 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractTimeSeriesCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractTimeSeriesCommands.java @@ -4,6 +4,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; import static io.smallrye.mutiny.helpers.ParameterValidation.positive; +import java.lang.reflect.Type; import java.time.Duration; import io.quarkus.redis.datasource.timeseries.AddArgs; @@ -23,7 +24,7 @@ public class AbstractTimeSeriesCommands extends AbstractRedisCommands { - AbstractTimeSeriesCommands(RedisCommandExecutor redis, Class k) { + AbstractTimeSeriesCommands(RedisCommandExecutor redis, Type k) { super(redis, new Marshaller(k)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractTopKCommands.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractTopKCommands.java index 9db2bead835bc..0559e08269d25 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractTopKCommands.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/AbstractTopKCommands.java @@ -5,6 +5,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; import static io.smallrye.mutiny.helpers.ParameterValidation.positive; +import java.lang.reflect.Type; import java.util.Map; import io.smallrye.mutiny.Uni; @@ -13,7 +14,7 @@ public class AbstractTopKCommands extends AbstractRedisCommands { - AbstractTopKCommands(RedisCommandExecutor redis, Class k, Class v) { + AbstractTopKCommands(RedisCommandExecutor redis, Type k, Type v) { super(redis, new Marshaller(k, v)); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/BlockingRedisDataSourceImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/BlockingRedisDataSourceImpl.java index 3a54d936bd2c2..fcf3d8c05af84 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/BlockingRedisDataSourceImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/BlockingRedisDataSourceImpl.java @@ -7,6 +7,8 @@ import java.util.function.Consumer; import java.util.function.Function; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.ReactiveRedisDataSource; import io.quarkus.redis.datasource.RedisDataSource; import io.quarkus.redis.datasource.autosuggest.AutoSuggestCommands; @@ -186,21 +188,42 @@ public HashCommands hash(Class redisKeyType, Class return new BlockingHashCommandsImpl<>(this, reactive.hash(redisKeyType, typeOfField, typeOfValue), timeout); } + @Override + public HashCommands hash(TypeReference redisKeyType, TypeReference typeOfField, + TypeReference typeOfValue) { + return new BlockingHashCommandsImpl<>(this, reactive.hash(redisKeyType, typeOfField, typeOfValue), timeout); + } + @Override public GeoCommands geo(Class redisKeyType, Class memberType) { return new BlockingGeoCommandsImpl<>(this, reactive.geo(redisKeyType, memberType), timeout); } + @Override + public GeoCommands geo(TypeReference redisKeyType, TypeReference memberType) { + return new BlockingGeoCommandsImpl<>(this, reactive.geo(redisKeyType, memberType), timeout); + } + @Override public KeyCommands key(Class redisKeyType) { return new BlockingKeyCommandsImpl<>(this, reactive.key(redisKeyType), timeout); } + @Override + public KeyCommands key(TypeReference redisKeyType) { + return new BlockingKeyCommandsImpl<>(this, reactive.key(redisKeyType), timeout); + } + @Override public SortedSetCommands sortedSet(Class redisKeyType, Class valueType) { return new BlockingSortedSetCommandsImpl<>(this, reactive.sortedSet(redisKeyType, valueType), timeout); } + @Override + public SortedSetCommands sortedSet(TypeReference redisKeyType, TypeReference valueType) { + return new BlockingSortedSetCommandsImpl<>(this, reactive.sortedSet(redisKeyType, valueType), timeout); + } + @Override public StringCommands string(Class redisKeyType, Class valueType) { return new BlockingStringCommandsImpl<>(this, reactive.value(redisKeyType, valueType), timeout); @@ -211,56 +234,112 @@ public ValueCommands value(Class redisKeyType, Class valueTyp return new BlockingStringCommandsImpl<>(this, reactive.value(redisKeyType, valueType), timeout); } + @Override + public ValueCommands value(TypeReference redisKeyType, TypeReference valueType) { + return new BlockingStringCommandsImpl<>(this, reactive.value(redisKeyType, valueType), timeout); + } + @Override public SetCommands set(Class redisKeyType, Class memberType) { return new BlockingSetCommandsImpl<>(this, reactive.set(redisKeyType, memberType), timeout); } + @Override + public SetCommands set(TypeReference redisKeyType, TypeReference memberType) { + return new BlockingSetCommandsImpl<>(this, reactive.set(redisKeyType, memberType), timeout); + } + @Override public ListCommands list(Class redisKeyType, Class memberType) { return new BlockingListCommandsImpl<>(this, reactive.list(redisKeyType, memberType), timeout); } + @Override + public ListCommands list(TypeReference redisKeyType, TypeReference memberType) { + return new BlockingListCommandsImpl<>(this, reactive.list(redisKeyType, memberType), timeout); + } + @Override public HyperLogLogCommands hyperloglog(Class redisKeyType, Class memberType) { return new BlockingHyperLogLogCommandsImpl<>(this, reactive.hyperloglog(redisKeyType, memberType), timeout); } + @Override + public HyperLogLogCommands hyperloglog(TypeReference redisKeyType, TypeReference memberType) { + return new BlockingHyperLogLogCommandsImpl<>(this, reactive.hyperloglog(redisKeyType, memberType), timeout); + } + @Override public BitMapCommands bitmap(Class redisKeyType) { return new BlockingBitmapCommandsImpl<>(this, reactive.bitmap(redisKeyType), timeout); } + @Override + public BitMapCommands bitmap(TypeReference redisKeyType) { + return new BlockingBitmapCommandsImpl<>(this, reactive.bitmap(redisKeyType), timeout); + } + @Override public StreamCommands stream(Class redisKeyType, Class fieldType, Class valueType) { return new BlockingStreamCommandsImpl<>(this, reactive.stream(redisKeyType, fieldType, valueType), timeout); } + @Override + public StreamCommands stream(TypeReference redisKeyType, TypeReference fieldType, + TypeReference valueType) { + return new BlockingStreamCommandsImpl<>(this, reactive.stream(redisKeyType, fieldType, valueType), timeout); + } + @Override public JsonCommands json(Class redisKeyType) { return new BlockingJsonCommandsImpl<>(this, reactive.json(redisKeyType), timeout); } + @Override + public JsonCommands json(TypeReference redisKeyType) { + return new BlockingJsonCommandsImpl<>(this, reactive.json(redisKeyType), timeout); + } + @Override public BloomCommands bloom(Class redisKeyType, Class valueType) { return new BlockingBloomCommandsImpl<>(this, reactive.bloom(redisKeyType, valueType), timeout); } + @Override + public BloomCommands bloom(TypeReference redisKeyType, TypeReference valueType) { + return new BlockingBloomCommandsImpl<>(this, reactive.bloom(redisKeyType, valueType), timeout); + } + @Override public CuckooCommands cuckoo(Class redisKeyType, Class valueType) { return new BlockingCuckooCommandsImpl<>(this, reactive.cuckoo(redisKeyType, valueType), timeout); } + @Override + public CuckooCommands cuckoo(TypeReference redisKeyType, TypeReference valueType) { + return new BlockingCuckooCommandsImpl<>(this, reactive.cuckoo(redisKeyType, valueType), timeout); + } + @Override public CountMinCommands countmin(Class redisKeyType, Class valueType) { return new BlockingCountMinCommandsImpl<>(this, reactive.countmin(redisKeyType, valueType), timeout); } + @Override + public CountMinCommands countmin(TypeReference redisKeyType, TypeReference valueType) { + return new BlockingCountMinCommandsImpl<>(this, reactive.countmin(redisKeyType, valueType), timeout); + } + @Override public TopKCommands topk(Class redisKeyType, Class valueType) { return new BlockingTopKCommandsImpl<>(this, reactive.topk(redisKeyType, valueType), timeout); } + @Override + public TopKCommands topk(TypeReference redisKeyType, TypeReference valueType) { + return new BlockingTopKCommandsImpl<>(this, reactive.topk(redisKeyType, valueType), timeout); + } + @Override public GraphCommands graph(Class redisKeyType) { return new BlockingGraphCommandsImpl<>(this, reactive.graph(redisKeyType), timeout); @@ -276,16 +355,31 @@ public AutoSuggestCommands autosuggest(Class redisKeyType) { return new BlockingAutoSuggestCommandsImpl<>(this, reactive.autosuggest(redisKeyType), timeout); } + @Override + public AutoSuggestCommands autosuggest(TypeReference redisKeyType) { + return new BlockingAutoSuggestCommandsImpl<>(this, reactive.autosuggest(redisKeyType), timeout); + } + @Override public TimeSeriesCommands timeseries(Class redisKeyType) { return new BlockingTimeSeriesCommandsImpl<>(this, reactive.timeseries(redisKeyType), timeout); } + @Override + public TimeSeriesCommands timeseries(TypeReference redisKeyType) { + return new BlockingTimeSeriesCommandsImpl<>(this, reactive.timeseries(redisKeyType), timeout); + } + @Override public PubSubCommands pubsub(Class messageType) { return new BlockingPubSubCommandsImpl<>(this, reactive.pubsub(messageType), timeout); } + @Override + public PubSubCommands pubsub(TypeReference messageType) { + return new BlockingPubSubCommandsImpl<>(this, reactive.pubsub(messageType), timeout); + } + @Override public Response execute(String command, String... args) { return reactive.execute(command, args) diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/HScanReactiveCursorImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/HScanReactiveCursorImpl.java index 8ed29a5081888..bbcfe3f1fc7ce 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/HScanReactiveCursorImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/HScanReactiveCursorImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -14,13 +15,13 @@ public class HScanReactiveCursorImpl extends AbstractRedisCommands implements ReactiveHashScanCursor { private final byte[] key; - private final Class typeOfField; - private final Class typeOfValue; + private final Type typeOfField; + private final Type typeOfValue; private long cursor; private final List extra = new ArrayList<>(); - public HScanReactiveCursorImpl(RedisCommandExecutor redis, K key, Marshaller marshaller, Class typeOfField, - Class typeOfValue, + public HScanReactiveCursorImpl(RedisCommandExecutor redis, K key, Marshaller marshaller, Type typeOfField, + Type typeOfValue, List extra) { super(redis, marshaller); this.key = marshaller.encode(key); diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/Marshaller.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/Marshaller.java index 74bf0ca39540d..fccf13c352fdf 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/Marshaller.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/Marshaller.java @@ -3,6 +3,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; @@ -15,6 +16,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.codecs.Codec; import io.quarkus.redis.datasource.codecs.Codecs; import io.vertx.mutiny.redis.client.Response; @@ -22,24 +25,19 @@ public class Marshaller { - private static final Map, Codec> DEFAULT_CODECS; - - static { - DEFAULT_CODECS = Map.of( - String.class, Codecs.StringCodec.INSTANCE, - Integer.class, Codecs.IntegerCodec.INSTANCE, - Double.class, Codecs.DoubleCodec.INSTANCE); - } + public static final TypeReference STRING_TYPE_REFERENCE = new TypeReference() { + // Empty on purpose + }; - Map, Codec> codecs = new ConcurrentHashMap<>(); + Map codecs = new ConcurrentHashMap<>(); - public Marshaller(Class... hints) { + public Marshaller(Type... hints) { addAll(hints); } - public void addAll(Class... hints) { + public void addAll(Type... hints) { doesNotContainNull(hints, "hints"); - for (Class hint : hints) { + for (Type hint : hints) { codecs.computeIfAbsent(hint, h -> Codecs.getDefaultCodecFor(hint)); } } @@ -71,7 +69,7 @@ public final List encode(T... objects) { return result; } - Codec codec(Class clazz) { + Codec codec(Type clazz) { Codec codec = codecs.get(clazz); if (codec == null) { codec = Codecs.getDefaultCodecFor(clazz); @@ -80,7 +78,7 @@ Codec codec(Class clazz) { return codec; } - public final T decode(Class clazz, Response r) { + public final T decode(Type clazz, Response r) { if (r == null) { return null; } @@ -91,7 +89,7 @@ public final T decode(Class clazz, Response r) { } @SuppressWarnings("unchecked") - public final T decode(Class clazz, byte[] r) { + public final T decode(Type clazz, byte[] r) { if (r == null) { return null; } @@ -99,7 +97,7 @@ public final T decode(Class clazz, byte[] r) { return (T) codec.decode(r); } - public Map decodeAsMap(Response response, Class typeOfField, Class typeOfValue) { + public Map decodeAsMap(Response response, Type typeOfField, Type typeOfValue) { if (response == null || response.size() == 0) { return Collections.emptyMap(); } @@ -129,7 +127,7 @@ public Map decodeAsMap(Response response, Class typeOfField, Cla return map; } - public List decodeAsList(Response response, Class typeOfItem) { + public List decodeAsList(Response response, Type typeOfItem) { if (response == null) { return Collections.emptyList(); } @@ -155,7 +153,7 @@ public List decodeAsList(Response response, Function mapper) return list; } - public Set decodeAsSet(Response response, Class typeOfItem) { + public Set decodeAsSet(Response response, Type typeOfItem) { if (response == null) { return Collections.emptySet(); } @@ -166,7 +164,7 @@ public Set decodeAsSet(Response response, Class typeOfItem) { return set; } - final Map decodeAsOrderedMap(Response response, Class typeOfValue, F[] fields) { + final Map decodeAsOrderedMap(Response response, Type typeOfValue, F[] fields) { Iterator iterator = response.iterator(); Map map = new LinkedHashMap<>(); for (F field : fields) { diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveAutoSuggestCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveAutoSuggestCommandsImpl.java index c4c1107d30867..d1701b45a78c6 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveAutoSuggestCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveAutoSuggestCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -16,7 +17,7 @@ public class ReactiveAutoSuggestCommandsImpl extends AbstractAutoSuggestComma private final ReactiveRedisDataSource reactive; - public ReactiveAutoSuggestCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k) { + public ReactiveAutoSuggestCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k) { super(redis, k); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveBitMapCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveBitMapCommandsImpl.java index db5552a1d8895..e4fc7aeec2ffd 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveBitMapCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveBitMapCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.List; import io.quarkus.redis.datasource.ReactiveRedisCommands; @@ -14,7 +15,7 @@ public class ReactiveBitMapCommandsImpl extends AbstractBitMapCommands private final ReactiveRedisDataSource reactive; - public ReactiveBitMapCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k) { + public ReactiveBitMapCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k) { super(redis, k); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveBloomCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveBloomCommandsImpl.java index acdfaff04797d..ceccab38b4fdf 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveBloomCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveBloomCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -15,7 +16,7 @@ public class ReactiveBloomCommandsImpl extends AbstractBloomCommands private final ReactiveRedisDataSource reactive; - public ReactiveBloomCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k, Class v) { + public ReactiveBloomCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveCountMinCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveCountMinCommandsImpl.java index f36b8919583a5..9441b1a84a8b9 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveCountMinCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveCountMinCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -16,7 +17,7 @@ public class ReactiveCountMinCommandsImpl extends AbstractCountMinCommands private final ReactiveRedisDataSource reactive; - public ReactiveCountMinCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k, Class v) { + public ReactiveCountMinCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveCuckooCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveCuckooCommandsImpl.java index 90ba51e670912..1562f411b793d 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveCuckooCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveCuckooCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.List; import io.quarkus.redis.datasource.ReactiveRedisCommands; @@ -15,7 +16,7 @@ public class ReactiveCuckooCommandsImpl extends AbstractCuckooCommands k, Class v) { + public ReactiveCuckooCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveGeoCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveGeoCommandsImpl.java index ba51529f48792..f401866a59d0e 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveGeoCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveGeoCommandsImpl.java @@ -2,6 +2,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.List; import java.util.Set; @@ -24,7 +25,7 @@ public class ReactiveGeoCommandsImpl extends AbstractGeoCommands imp static final GeoAddArgs DEFAULT_INSTANCE = new GeoAddArgs(); private final ReactiveRedisDataSource reactive; - public ReactiveGeoCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k, Class v) { + public ReactiveGeoCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveHashCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveHashCommandsImpl.java index c39ae6327d96d..11fd01643f2a8 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveHashCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveHashCommandsImpl.java @@ -2,6 +2,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.Collections; import java.util.List; import java.util.Map; @@ -17,7 +18,7 @@ public class ReactiveHashCommandsImpl extends AbstractHashCommands k, Class f, Class v) { + public ReactiveHashCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type f, Type v) { super(redis, k, f, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveHyperLogLogCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveHyperLogLogCommandsImpl.java index ee69f4339ff3d..025b74f33491a 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveHyperLogLogCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveHyperLogLogCommandsImpl.java @@ -1,5 +1,7 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; + import io.quarkus.redis.datasource.ReactiveRedisDataSource; import io.quarkus.redis.datasource.hyperloglog.ReactiveHyperLogLogCommands; import io.smallrye.mutiny.Uni; @@ -10,7 +12,7 @@ public class ReactiveHyperLogLogCommandsImpl extends AbstractHyperLogLogCo private final ReactiveRedisDataSource reactive; - public ReactiveHyperLogLogCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k, Class v) { + public ReactiveHyperLogLogCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveJsonCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveJsonCommandsImpl.java index 3284ddfbfb05f..df831f492c9a2 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveJsonCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveJsonCommandsImpl.java @@ -2,6 +2,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -19,7 +20,7 @@ public class ReactiveJsonCommandsImpl extends AbstractJsonCommands impleme private final ReactiveRedisDataSource reactive; - public ReactiveJsonCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k) { + public ReactiveJsonCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k) { super(redis, k); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveKeyCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveKeyCommandsImpl.java index 2be9e365cb41d..3042daff48ae7 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveKeyCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveKeyCommandsImpl.java @@ -2,6 +2,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.time.Duration; import java.time.Instant; import java.util.Collections; @@ -21,7 +22,7 @@ public class ReactiveKeyCommandsImpl extends AbstractKeyCommands implement private final ReactiveRedisDataSource reactive; - public ReactiveKeyCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k) { + public ReactiveKeyCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k) { super(redis, k); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveListCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveListCommandsImpl.java index 0e68e6e7c824b..c76570e54f6ec 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveListCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveListCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.time.Duration; import java.util.List; @@ -15,7 +16,7 @@ public class ReactiveListCommandsImpl extends AbstractListCommands i private final ReactiveRedisDataSource reactive; - public ReactiveListCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k, Class v) { + public ReactiveListCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactivePubSubCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactivePubSubCommandsImpl.java index c3a935f13efde..10a92a867921d 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactivePubSubCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactivePubSubCommandsImpl.java @@ -4,6 +4,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.doesNotContainNull; import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -30,11 +31,11 @@ public class ReactivePubSubCommandsImpl extends AbstractRedisCommands implements ReactivePubSubCommands { - private final Class classOfMessage; + private final Type classOfMessage; private final Redis client; private final ReactiveRedisDataSourceImpl datasource; - public ReactivePubSubCommandsImpl(ReactiveRedisDataSourceImpl ds, Class classOfMessage) { + public ReactivePubSubCommandsImpl(ReactiveRedisDataSourceImpl ds, Type classOfMessage) { super(ds, new Marshaller(classOfMessage)); this.client = ds.redis; this.datasource = ds; diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveRedisDataSourceImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveRedisDataSourceImpl.java index 4819b478e4900..0908b98ac0487 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveRedisDataSourceImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveRedisDataSourceImpl.java @@ -9,6 +9,8 @@ import java.util.function.BiFunction; import java.util.function.Function; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.ReactiveRedisDataSource; import io.quarkus.redis.datasource.autosuggest.ReactiveAutoSuggestCommands; import io.quarkus.redis.datasource.bitmap.ReactiveBitMapCommands; @@ -105,7 +107,6 @@ public Uni withTransaction(Function { ReactiveRedisDataSourceImpl singleConnectionDS = new ReactiveRedisDataSourceImpl(vertx, redis, connection); - List watched = List.of(keys); TransactionHolder th = new TransactionHolder(); return watch(connection, keys) // WATCH keys .chain(() -> connection.send(Request.cmd(Command.MULTI)) @@ -242,21 +243,42 @@ public ReactiveHashCommands hash(Class redisKeyType, Class return new ReactiveHashCommandsImpl<>(this, redisKeyType, fieldType, valueType); } + @Override + public ReactiveHashCommands hash(TypeReference redisKeyType, TypeReference fieldType, + TypeReference valueType) { + return new ReactiveHashCommandsImpl<>(this, redisKeyType.getType(), fieldType.getType(), valueType.getType()); + } + @Override public ReactiveGeoCommands geo(Class redisKeyType, Class memberType) { return new ReactiveGeoCommandsImpl<>(this, redisKeyType, memberType); } + @Override + public ReactiveGeoCommands geo(TypeReference redisKeyType, TypeReference memberType) { + return new ReactiveGeoCommandsImpl<>(this, redisKeyType.getType(), memberType.getType()); + } + @Override public ReactiveKeyCommands key(Class redisKeyType) { return new ReactiveKeyCommandsImpl<>(this, redisKeyType); } + @Override + public ReactiveKeyCommands key(TypeReference redisKeyType) { + return new ReactiveKeyCommandsImpl<>(this, redisKeyType.getType()); + } + @Override public ReactiveSortedSetCommands sortedSet(Class redisKeyType, Class valueType) { return new ReactiveSortedSetCommandsImpl<>(this, redisKeyType, valueType); } + @Override + public ReactiveSortedSetCommands sortedSet(TypeReference redisKeyType, TypeReference valueType) { + return new ReactiveSortedSetCommandsImpl<>(this, redisKeyType.getType(), valueType.getType()); + } + @Override public ReactiveStringCommands string(Class redisKeyType, Class valueType) { return new ReactiveStringCommandsImpl<>(this, redisKeyType, valueType); @@ -267,56 +289,112 @@ public ReactiveValueCommands value(Class redisKeyType, Class return new ReactiveStringCommandsImpl<>(this, redisKeyType, valueType); } + @Override + public ReactiveValueCommands value(TypeReference redisKeyType, TypeReference valueType) { + return new ReactiveStringCommandsImpl<>(this, redisKeyType.getType(), valueType.getType()); + } + @Override public ReactiveSetCommands set(Class redisKeyType, Class memberType) { return new ReactiveSetCommandsImpl<>(this, redisKeyType, memberType); } + @Override + public ReactiveSetCommands set(TypeReference redisKeyType, TypeReference memberType) { + return new ReactiveSetCommandsImpl<>(this, redisKeyType.getType(), memberType.getType()); + } + @Override public ReactiveListCommands list(Class redisKeyType, Class memberType) { return new ReactiveListCommandsImpl<>(this, redisKeyType, memberType); } + @Override + public ReactiveListCommands list(TypeReference redisKeyType, TypeReference memberType) { + return new ReactiveListCommandsImpl<>(this, redisKeyType.getType(), memberType.getType()); + } + @Override public ReactiveHyperLogLogCommands hyperloglog(Class redisKeyType, Class memberType) { return new ReactiveHyperLogLogCommandsImpl<>(this, redisKeyType, memberType); } + @Override + public ReactiveHyperLogLogCommands hyperloglog(TypeReference redisKeyType, TypeReference memberType) { + return new ReactiveHyperLogLogCommandsImpl<>(this, redisKeyType.getType(), memberType.getType()); + } + @Override public ReactiveBitMapCommands bitmap(Class redisKeyType) { return new ReactiveBitMapCommandsImpl<>(this, redisKeyType); } + @Override + public ReactiveBitMapCommands bitmap(TypeReference redisKeyType) { + return new ReactiveBitMapCommandsImpl<>(this, redisKeyType.getType()); + } + @Override public ReactiveStreamCommands stream(Class redisKeyType, Class fieldType, Class valueType) { return new ReactiveStreamCommandsImpl<>(this, redisKeyType, fieldType, valueType); } + @Override + public ReactiveStreamCommands stream(TypeReference redisKeyType, TypeReference fieldType, + TypeReference valueType) { + return new ReactiveStreamCommandsImpl<>(this, redisKeyType.getType(), fieldType.getType(), valueType.getType()); + } + @Override public ReactiveJsonCommands json(Class redisKeyType) { return new ReactiveJsonCommandsImpl<>(this, redisKeyType); } + @Override + public ReactiveJsonCommands json(TypeReference redisKeyType) { + return new ReactiveJsonCommandsImpl<>(this, redisKeyType.getType()); + } + @Override public ReactiveBloomCommands bloom(Class redisKeyType, Class valueType) { return new ReactiveBloomCommandsImpl<>(this, redisKeyType, valueType); } + @Override + public ReactiveBloomCommands bloom(TypeReference redisKeyType, TypeReference valueType) { + return new ReactiveBloomCommandsImpl<>(this, redisKeyType.getType(), valueType.getType()); + } + @Override public ReactiveCuckooCommands cuckoo(Class redisKeyType, Class valueType) { return new ReactiveCuckooCommandsImpl<>(this, redisKeyType, valueType); } + @Override + public ReactiveCuckooCommands cuckoo(TypeReference redisKeyType, TypeReference valueType) { + return new ReactiveCuckooCommandsImpl<>(this, redisKeyType.getType(), valueType.getType()); + } + @Override public ReactiveCountMinCommands countmin(Class redisKeyType, Class valueType) { return new ReactiveCountMinCommandsImpl<>(this, redisKeyType, valueType); } + @Override + public ReactiveCountMinCommands countmin(TypeReference redisKeyType, TypeReference valueType) { + return new ReactiveCountMinCommandsImpl<>(this, redisKeyType.getType(), valueType.getType()); + } + @Override public ReactiveTopKCommands topk(Class redisKeyType, Class valueType) { return new ReactiveTopKCommandsImpl<>(this, redisKeyType, valueType); } + @Override + public ReactiveTopKCommands topk(TypeReference redisKeyType, TypeReference valueType) { + return new ReactiveTopKCommandsImpl<>(this, redisKeyType.getType(), valueType.getType()); + } + @Override public ReactiveGraphCommands graph(Class redisKeyType) { return new ReactiveGraphCommandsImpl<>(this, redisKeyType); @@ -327,6 +405,11 @@ public ReactivePubSubCommands pubsub(Class messageType) { return new ReactivePubSubCommandsImpl<>(this, messageType); } + @Override + public ReactivePubSubCommands pubsub(TypeReference messageType) { + return new ReactivePubSubCommandsImpl<>(this, messageType.getType()); + } + @Override public ReactiveSearchCommands search(Class redisKeyType) { return new ReactiveSearchCommandsImpl<>(this, redisKeyType); @@ -337,11 +420,21 @@ public ReactiveAutoSuggestCommands autosuggest(Class redisKeyType) { return new ReactiveAutoSuggestCommandsImpl<>(this, redisKeyType); } + @Override + public ReactiveAutoSuggestCommands autosuggest(TypeReference redisKeyType) { + return new ReactiveAutoSuggestCommandsImpl<>(this, redisKeyType.getType()); + } + @Override public ReactiveTimeSeriesCommands timeseries(Class redisKeyType) { return new ReactiveTimeSeriesCommandsImpl<>(this, redisKeyType); } + @Override + public ReactiveTimeSeriesCommands timeseries(TypeReference redisKeyType) { + return new ReactiveTimeSeriesCommandsImpl<>(this, redisKeyType.getType()); + } + @Override public Redis getRedis() { return redis; diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSearchCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSearchCommandsImpl.java index 2dbc99dd966b2..872d2a3f0a210 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSearchCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSearchCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -30,9 +31,9 @@ public class ReactiveSearchCommandsImpl extends AbstractSearchCommands implements ReactiveSearchCommands, ReactiveRedisCommands { private final ReactiveRedisDataSource reactive; - protected final Class keyType; + protected final Type keyType; - public ReactiveSearchCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k) { + public ReactiveSearchCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k) { super(redis, k); this.reactive = redis; this.keyType = k; diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSetCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSetCommandsImpl.java index 2cda5ea9f5a23..4a2b0ca37af32 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSetCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSetCommandsImpl.java @@ -2,6 +2,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.Collections; import java.util.List; import java.util.Set; @@ -17,7 +18,7 @@ public class ReactiveSetCommandsImpl extends AbstractSetCommands imp private final ReactiveRedisDataSource reactive; - public ReactiveSetCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k, Class v) { + public ReactiveSetCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSortable.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSortable.java index d571ce689b2da..ebd0cd916408d 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSortable.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSortable.java @@ -2,6 +2,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.util.List; import io.quarkus.redis.datasource.SortArgs; @@ -11,11 +12,11 @@ public class ReactiveSortable extends AbstractRedisCommands { - private final Class typeOfValue; + private final Type typeOfValue; private static final SortArgs DEFAULT_INSTANCE = new SortArgs(); - public ReactiveSortable(RedisCommandExecutor redis, Marshaller marshaller, Class typeOfValue) { + public ReactiveSortable(RedisCommandExecutor redis, Marshaller marshaller, Type typeOfValue) { super(redis, marshaller); this.typeOfValue = typeOfValue; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSortedSetCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSortedSetCommandsImpl.java index f2aa3e5dd65ab..46ad8aba555f2 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSortedSetCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveSortedSetCommandsImpl.java @@ -3,6 +3,7 @@ import static io.smallrye.mutiny.helpers.ParameterValidation.nonNull; +import java.lang.reflect.Type; import java.time.Duration; import java.util.Collections; import java.util.List; @@ -27,7 +28,7 @@ public class ReactiveSortedSetCommandsImpl extends AbstractSortedSetComman private final ReactiveRedisDataSource reactive; - public ReactiveSortedSetCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k, Class v) { + public ReactiveSortedSetCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveStreamCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveStreamCommandsImpl.java index cc0638a66ee6e..ca566c31b7dde 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveStreamCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveStreamCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; @@ -30,11 +31,11 @@ public class ReactiveStreamCommandsImpl extends AbstractStreamCommands< implements ReactiveStreamCommands, ReactiveRedisCommands { private final ReactiveRedisDataSource reactive; - private final Class typeOfValue; - private final Class typeOfField; - private final Class typeOfKey; + private final Type typeOfValue; + private final Type typeOfField; + private final Type typeOfKey; - public ReactiveStreamCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k, Class f, Class v) { + public ReactiveStreamCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type f, Type v) { super(redis, k, f, v); this.typeOfKey = k; this.typeOfField = f; @@ -97,7 +98,7 @@ protected List> decodeMessageListPrefixedByKey(Response r if (r == null) { return List.of(); } - var actualKey = marshaller.decode(typeOfKey, r.get(0)); + K actualKey = marshaller.decode(typeOfKey, r.get(0)); var listOfMessages = r.get(1); List> list = new ArrayList<>(); for (int i = 0; i < listOfMessages.size(); i++) { diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveStringCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveStringCommandsImpl.java index ef0df74339db3..3e96e4c0e2921 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveStringCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveStringCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.Map; import io.quarkus.redis.datasource.ReactiveRedisDataSource; @@ -15,7 +16,7 @@ public class ReactiveStringCommandsImpl extends AbstractStringCommands k, Class v) { + public ReactiveStringCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.reactive = redis; } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveTimeSeriesCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveTimeSeriesCommandsImpl.java index cc29f58e7fc90..a84193d9f1a54 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveTimeSeriesCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveTimeSeriesCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; @@ -31,9 +32,9 @@ public class ReactiveTimeSeriesCommandsImpl extends AbstractTimeSeriesCommand implements ReactiveTimeSeriesCommands, ReactiveRedisCommands { private final ReactiveRedisDataSource reactive; - protected final Class keyType; + protected final Type keyType; - public ReactiveTimeSeriesCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k) { + public ReactiveTimeSeriesCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k) { super(redis, k); this.keyType = k; this.reactive = redis; diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveTopKCommandsImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveTopKCommandsImpl.java index b4981b47990ea..bc0026be809d6 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveTopKCommandsImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactiveTopKCommandsImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -15,9 +16,9 @@ public class ReactiveTopKCommandsImpl extends AbstractTopKCommands implements ReactiveTopKCommands, ReactiveRedisCommands { private final ReactiveRedisDataSource reactive; - final Class typeOfValue; + final Type typeOfValue; - public ReactiveTopKCommandsImpl(ReactiveRedisDataSourceImpl redis, Class k, Class v) { + public ReactiveTopKCommandsImpl(ReactiveRedisDataSourceImpl redis, Type k, Type v) { super(redis, k, v); this.typeOfValue = v; this.reactive = redis; @@ -31,7 +32,7 @@ public ReactiveRedisDataSource getDataSource() { @Override public Uni topkAdd(K key, V item) { return super._topkAdd(key, item) - .map(r -> marshaller.decodeAsList(r, typeOfValue).get(0)); + .map(r -> marshaller. decodeAsList(r, typeOfValue).get(0)); } @Override @@ -43,7 +44,7 @@ public Uni> topkAdd(K key, V... items) { @Override public Uni topkIncrBy(K key, V item, int increment) { return super._topkIncrBy(key, item, increment) - .map(r -> marshaller.decodeAsList(r, typeOfValue).get(0)); + .map(r -> marshaller. decodeAsList(r, typeOfValue).get(0)); } @Override diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/SScanReactiveCursorImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/SScanReactiveCursorImpl.java index c129961aa5893..0e4112f67fb95 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/SScanReactiveCursorImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/SScanReactiveCursorImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -13,13 +14,13 @@ public class SScanReactiveCursorImpl extends AbstractRedisCommands implements ReactiveSScanCursor { private final byte[] key; - private final Class typeOfValue; + private final Type typeOfValue; private final Marshaller marshaller; private long cursor; private final List extra = new ArrayList<>(); public SScanReactiveCursorImpl(RedisCommandExecutor redis, K key, Marshaller marshaller, - Class typeOfValue, List extra) { + Type typeOfValue, List extra) { super(redis, marshaller); this.key = marshaller.encode(key); this.cursor = ReactiveCursor.INITIAL_CURSOR_ID; diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ScanReactiveCursorImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ScanReactiveCursorImpl.java index 7ed11d879d716..000009a126d9d 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ScanReactiveCursorImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ScanReactiveCursorImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -12,11 +13,11 @@ public class ScanReactiveCursorImpl extends AbstractRedisCommands implements ReactiveKeyScanCursor { - private final Class typeOfKey; + private final Type typeOfKey; private long cursor; private final List extra = new ArrayList<>(); - public ScanReactiveCursorImpl(RedisCommandExecutor redis, Marshaller marshaller, Class typeOfKey, List extra) { + public ScanReactiveCursorImpl(RedisCommandExecutor redis, Marshaller marshaller, Type typeOfKey, List extra) { super(redis, marshaller); this.cursor = ReactiveCursor.INITIAL_CURSOR_ID; this.typeOfKey = typeOfKey; diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ZScanReactiveCursorImpl.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ZScanReactiveCursorImpl.java index 720ac7c1501b7..8810ec1ab0f31 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ZScanReactiveCursorImpl.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ZScanReactiveCursorImpl.java @@ -1,5 +1,6 @@ package io.quarkus.redis.runtime.datasource; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -13,11 +14,11 @@ public class ZScanReactiveCursorImpl extends AbstractRedisCommands implements ReactiveZScanCursor { private final byte[] key; - private final Class typeOfValue; + private final Type typeOfValue; private long cursor; private final List extra = new ArrayList<>(); - public ZScanReactiveCursorImpl(RedisCommandExecutor redis, K key, Marshaller marshaller, Class typeOfValue, + public ZScanReactiveCursorImpl(RedisCommandExecutor redis, K key, Marshaller marshaller, Type typeOfValue, List extra) { super(redis, marshaller); this.key = marshaller.encode(key); diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/AutoSuggestCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/AutoSuggestCommandsTest.java index 03eb4506d85e0..7b4e7fd7eb1a7 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/AutoSuggestCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/AutoSuggestCommandsTest.java @@ -4,11 +4,14 @@ import static org.awaitility.Awaitility.await; import java.time.Duration; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.autosuggest.AutoSuggestCommands; import io.quarkus.redis.datasource.autosuggest.GetArgs; import io.quarkus.redis.runtime.datasource.BlockingRedisDataSourceImpl; @@ -87,4 +90,58 @@ void testSuggestions() { }); } + @Test + void testSuggestionsWithTypeReference() { + var auto = ds.autosuggest(new TypeReference>() { + // Empty on purpose. + }); + + List key = List.of(Person.person0); + + assertThat(auto.ftSugAdd(key, "hello world", 1)).isEqualTo(1L); + assertThat(auto.ftSugAdd(key, "hello world", 3, true)).isEqualTo(1L); + + assertThat(auto.ftSugAdd(key, "bonjour", 3)).isEqualTo(2L); + assertThat(auto.ftSugAdd(key, "bonjourno", 1)).isEqualTo(3L); + + assertThat(auto.ftSugLen(key)).isEqualTo(3L); + assertThat(auto.ftSugDel(key, "bonjourno")).isTrue(); + assertThat(auto.ftSugDel(key, "missing")).isFalse(); + + assertThat(auto.ftSugLen(key)).isEqualTo(2L); + + assertThat(auto.ftSugAdd(key, "hell", 3)).isEqualTo(3L); + + assertThat(auto.ftSugGet(key, "hell")).hasSize(2) + .anySatisfy(s -> assertThat(s.suggestion()).isEqualTo("hell")) + .anySatisfy(s -> assertThat(s.suggestion()).isEqualTo("hello world")); + + assertThat(auto.ftSugGet(key, "hel", new GetArgs().max(1).withScores())).hasSize(1) + .anySatisfy(s -> { + assertThat(s.suggestion()).isEqualTo("hell"); + assertThat(s.score()).isGreaterThan(0.0); + }); + + assertThat(auto.ftSugAdd(key, "hill", 3)).isEqualTo(4L); + + assertThat(auto.ftSugGet(key, "hell", new GetArgs().fuzzy())).hasSize(3) + .anySatisfy(s -> assertThat(s.suggestion()).isEqualTo("hell")) + .anySatisfy(s -> assertThat(s.suggestion()).isEqualTo("hello world")) + .anySatisfy(s -> assertThat(s.suggestion()).isEqualTo("hill")); + + assertThat(auto.ftSugGet(key, "hell", new GetArgs().fuzzy().withScores())).hasSize(3) + .anySatisfy(s -> { + assertThat(s.suggestion()).isEqualTo("hell"); + assertThat(s.score()).isGreaterThan(0.0); + }) + .anySatisfy(s -> { + assertThat(s.suggestion()).isEqualTo("hello world"); + assertThat(s.score()).isGreaterThan(0.0); + }) + .anySatisfy(s -> { + assertThat(s.suggestion()).isEqualTo("hill"); + assertThat(s.score()).isGreaterThan(0.0); + }); + } + } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/BitMapCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/BitMapCommandsTest.java index 29c036180288f..f67048b51a2ca 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/BitMapCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/BitMapCommandsTest.java @@ -16,6 +16,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.bitmap.BitFieldArgs; import io.quarkus.redis.datasource.bitmap.BitMapCommands; import io.quarkus.redis.runtime.datasource.BlockingRedisDataSourceImpl; @@ -208,4 +210,20 @@ void setbit() { assertThat(bitmap.setbit(key, 0, 1)).isEqualTo(0); assertThat(bitmap.setbit(key, 0, 0)).isEqualTo(1); } + + @Test + void bitcountWithTypeReference() { + var bitmap = ds.bitmap(new TypeReference>() { + // Empty on purpose + }); + List key = List.of("a", "b", "c"); + assertThat(bitmap.bitcount(key)).isEqualTo(0); + + bitmap.setbit(key, 0L, 1); + bitmap.setbit(key, 1L, 1); + bitmap.setbit(key, 2L, 1); + + assertThat(bitmap.bitcount(key)).isEqualTo(3); + assertThat(bitmap.bitcount(key, 3, -1)).isEqualTo(0); + } } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/BloomCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/BloomCommandsTest.java index 4bfc034777d61..db23fe57e9149 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/BloomCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/BloomCommandsTest.java @@ -4,11 +4,14 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.time.Duration; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.bloom.BfInsertArgs; import io.quarkus.redis.datasource.bloom.BfReserveArgs; import io.quarkus.redis.datasource.bloom.BloomCommands; @@ -100,7 +103,22 @@ void bfinsert() { assertThatThrownBy(() -> bloom.bfinsert("key2", new BfInsertArgs().capacity(600000).errorRate(0.0001).nonScaling().nocreate(), luke, leia, anakin)); assertThatThrownBy(() -> bloom.bfinsert("key3", new BfInsertArgs().capacity(600000).errorRate(0.0001).expansion(1))); + } + @Test + void bloomWithTypeReference() { + var bloom = ds.bloom(new TypeReference>() { + // Empty on purpose. + }); + var l1 = List.of(Person.person1, Person.person2); + var l2 = List.of(Person.person1, Person.person3); + assertThat(bloom.bfadd(key, l1)).isTrue(); + + assertThat(bloom.bfexists(key, l1)).isTrue(); + assertThat(bloom.bfexists(key, l2)).isFalse(); + + assertThat(bloom.bfadd(key, l1)).isFalse(); + assertThat(bloom.bfadd(key, l2)).isTrue(); } } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/CountMinCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/CountMinCommandsTest.java index b02bbc2b8550e..70b4b75eaf83d 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/CountMinCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/CountMinCommandsTest.java @@ -12,6 +12,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.countmin.CountMinCommands; import io.quarkus.redis.runtime.datasource.BlockingRedisDataSourceImpl; @@ -104,4 +106,24 @@ void mergeWithoutWeights() { assertThat(cm.cmsQuery(key, luke)).isEqualTo(5L); } + @Test + void countMinWithTypeReference() { + Person luke = new Person("luke", "skywalker"); + Person leia = new Person("leia", "ordana"); + Person anakin = new Person("anakin", "skywalker"); + + var cm = ds.countmin(new TypeReference>() { + // Empty on purpose + }); + + cm.cmsInitByDim(key, 10, 2); + assertThat(cm.cmsIncrBy(key, List.of(leia, luke), 10)).isEqualTo(10); + assertThat(cm.cmsIncrBy(key, Map.of(List.of(leia, luke), 2L, List.of(luke, anakin), 5L, List.of(anakin), 3L))) + .contains(entry(List.of(leia, luke), 12L), entry(List.of(luke, anakin), 5L), entry(List.of(anakin), 3L)) + .hasSize(3); + + assertThat(cm.cmsQuery(key, List.of(anakin))).isEqualTo(3); + assertThat(cm.cmsQuery(key, List.of(leia, luke), List.of(luke, anakin))).containsExactly(12L, 5L); + } + } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/CuckooCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/CuckooCommandsTest.java index a90f502ef315f..99e36fd7b0a3c 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/CuckooCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/CuckooCommandsTest.java @@ -4,11 +4,14 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.time.Duration; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.cuckoo.CfInsertArgs; import io.quarkus.redis.datasource.cuckoo.CfReserveArgs; import io.quarkus.redis.datasource.cuckoo.CuckooCommands; @@ -145,4 +148,21 @@ void cfreserve() { assertThat(cuckoo.cfmexists("key3", luke, anakin, leia)).containsExactly(true, true, true); } + @Test + void cuckooWithTypeReference() { + var cuckoo = ds.cuckoo(new TypeReference>() { + // Empty on purpose. + }); + var l1 = List.of(Person.person1, Person.person2); + var l2 = List.of(Person.person1, Person.person3); + cuckoo.cfadd(key, l1); + + assertThat(cuckoo.cfexists(key, l1)).isTrue(); + assertThat(cuckoo.cfexists(key, l2)).isFalse(); + + assertThat(cuckoo.cfaddnx(key, l1)).isFalse(); + cuckoo.cfadd(key, l2); + assertThat(cuckoo.cfexists(key, l2)).isTrue(); + } + } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/GeoCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/GeoCommandsTest.java index beb076f528d75..85e3c36605fdd 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/GeoCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/GeoCommandsTest.java @@ -6,6 +6,7 @@ import java.time.Duration; import java.util.List; +import java.util.Map; import java.util.OptionalDouble; import java.util.Set; @@ -15,6 +16,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.geo.GeoAddArgs; import io.quarkus.redis.datasource.geo.GeoCommands; import io.quarkus.redis.datasource.geo.GeoItem; @@ -90,6 +93,31 @@ void geoadd() { assertThat(added).isTrue(); } + @Test + void geoaddUsingTypeReferences() { + var g = ds.geo(new TypeReference>() { + // Empty on purpose + }); + + boolean added = g.geoadd(key, 44.9396, CRUSSOL_LATITUDE, Map.of("a", Place.crussol)); + assertThat(added).isTrue(); + + added = g.geoadd(key, 44.9396, CRUSSOL_LATITUDE, Map.of("a", Place.crussol)); + assertThat(added).isFalse(); + + added = g.geoadd(key, GeoPosition.of(GRIGNAN_LONGITUDE, GRIGNAN_LATITUDE), Map.of("a", Place.grignan)); + assertThat(added).isTrue(); + + added = g.geoadd(key, GeoItem.of(Map.of("a", Place.suze), SUZE_LONGITUDE, SUZE_LATITUDE)); + assertThat(added).isTrue(); + + List>> list = g.geosearch(key, new GeoSearchArgs>() + .byRadius(60, GeoUnit.KM).fromMember(Map.of("a", Place.crussol)).ascending().withDistance()); + assertThat(list).hasSize(2); + assertThat(list.get(0).member).isEqualTo(Map.of("a", Place.crussol)); + assertThat(list.get(1).member).isEqualTo(Map.of("a", Place.grignan)); // 58 Km from crussol + } + @Test @RequiresRedis6OrHigher void geoaddWithNx() { diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/HashCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/HashCommandsTest.java index 1c799b2e67e24..3d09274485c92 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/HashCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/HashCommandsTest.java @@ -17,6 +17,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.hash.HashCommands; import io.quarkus.redis.datasource.hash.HashScanCursor; import io.quarkus.redis.runtime.datasource.BlockingRedisDataSourceImpl; @@ -54,6 +56,34 @@ void simpleHset() { assertThat(person).isNull(); } + @Test + void HSetWithTypeReference() { + var h = ds.hash(new TypeReference>() { + // Empty on purpose. + }); + h.hset("my-hash", "l1", List.of(Person.person1, Person.person2)); + List person = h.hget("my-hash", "l1"); + assertThat(person).containsExactly(Person.person1, Person.person2); + + assertThat(h.hdel("my-hash", "l1")).isEqualTo(1); + person = h.hget("my-hash", "l1"); + assertThat(person).isNull(); + } + + @Test + void HSetWithTypeReferenceUsingMaps() { + var h = ds.hash(new TypeReference>() { + // Empty on purpose. + }); + h.hset("my-hash", "l1", Map.of("a", Person.person1, "b", Person.person2)); + Map person = h.hget("my-hash", "l1"); + assertThat(person).containsOnly(entry("a", Person.person1), entry("b", Person.person2)); + + assertThat(h.hdel("my-hash", "l1")).isEqualTo(1); + person = h.hget("my-hash", "l1"); + assertThat(person).isNull(); + } + @Test void hdel() { assertThat(hash.hdel(key, "one")).isEqualTo(0); diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/HyperLogLogCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/HyperLogLogCommandsTest.java index d8340f05a70ea..1658c02f95e9a 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/HyperLogLogCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/HyperLogLogCommandsTest.java @@ -4,12 +4,15 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.time.Duration; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.hyperloglog.HyperLogLogCommands; import io.quarkus.redis.runtime.datasource.BlockingRedisDataSourceImpl; @@ -116,4 +119,17 @@ void pfaddPfmergePfCount() { assertThat(hll.pfcount(k2)).isEqualTo(3); } + @Test + void pfaddWithTypeReference() { + String k = getKey(); + var hll = ds.hyperloglog(new TypeReference>() { + // Empty on purpose + }); + var l1 = List.of(Person.person1, Person.person2); + var l2 = List.of(Person.person3, Person.person2); + assertThat(hll.pfadd(k, l1, l2)).isTrue(); + assertThat(hll.pfadd(k, l1, l1)).isFalse(); + Assertions.assertThat(hll.pfadd(k, l1)).isFalse(); + } + } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/JsonCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/JsonCommandsTest.java index 73e68ea63ea14..2d2ef0c81d561 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/JsonCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/JsonCommandsTest.java @@ -13,6 +13,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.json.JsonCommands; import io.quarkus.redis.datasource.json.JsonSetArgs; import io.quarkus.redis.runtime.datasource.BlockingRedisDataSourceImpl; @@ -494,7 +496,23 @@ void type() { assertThat(json.jsonType(key, "$.arr[0]")).containsExactly("integer"); assertThat(json.jsonType("empty", "$")).containsExactly("object"); assertThat(json.jsonType("empty", "$.a")).isEmpty(); + } + + @Test + public void testJsonWithTypeReference() { + var json = ds.json(new TypeReference>() { + // Empty on purpose + }); + + var key = List.of("a", "b", "c"); + json.jsonSet(key, "$", + new JsonObject().put("a", 2).put("b", 3).put("nested", new JsonObject().put("a", 4).put("b", null))); + assertThat(json.jsonGet(key, "$..b")).containsExactly(3, null); + JsonObject object = json.jsonGet(key, "..a", "$..b"); + assertThat(object).hasSize(2); + assertThat(object.getJsonArray("..a")).containsExactly(2, 4); + assertThat(object.getJsonArray("$..b")).containsExactly(3, null); } } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/KeyCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/KeyCommandsTest.java index 4c68e0fa65b57..c99ae509b5a3c 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/KeyCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/KeyCommandsTest.java @@ -17,6 +17,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.keys.CopyArgs; import io.quarkus.redis.datasource.keys.ExpireArgs; import io.quarkus.redis.datasource.keys.KeyCommands; @@ -192,6 +194,30 @@ void keys() { assertThat(k.contains("two")).isTrue(); } + @Test + void keysWithTypeReferences() { + var v = ds.value(new TypeReference>() { + // Empty on purpose + }, new TypeReference() { + // Empty on purpose + }); + var k = ds.key(new TypeReference>() { + // Empty on purpose + }); + + assertThat(k.keys("*")).isEqualTo(List.of()); + Map, Person> map = new LinkedHashMap<>(); + map.put(List.of("one"), Person.person1); + map.put(List.of("two"), Person.person2); + map.put(List.of("three"), Person.person3); + v.mset(map); + var l = k.keys("*o*"); + assertThat(l).hasSize(2); + assertThat(l.contains(List.of("one"))).isTrue(); + assertThat(l.contains(List.of("two"))).isTrue(); + assertThat(l.contains(List.of("three"))).isFalse(); + } + @Test public void move() { ds.withConnection(connection -> { diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/ListCommandTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/ListCommandTest.java index 5b1b983cea2cf..f4ebd437e694e 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/ListCommandTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/ListCommandTest.java @@ -13,6 +13,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.core.type.TypeReference; import io.quarkus.redis.datasource.list.KeyValue; import io.quarkus.redis.datasource.list.LPosArgs; @@ -356,6 +357,19 @@ void sort() { assertThat(commands.lpop("dest2", 100)).containsExactly("1", "2", "3", "4", "5", "5", "6", "7", "8", "9"); } + @Test + void testListWithTypeReference() { + var lists = ds.list(new TypeReference>() { + // Empty on purpose + }); + + var l1 = List.of(Person.person1, Person.person2); + var l2 = List.of(Person.person1, Person.person3); + + lists.rpush(key, l1, l2); + assertThat(lists.blpop(Duration.ofSeconds(1), "one", key)).isEqualTo(KeyValue.of(key, l1)); + } + @Test void testJacksonPolymorphism() { var cmd = ds.list(Animal.class); diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/PubSubCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/PubSubCommandsTest.java index 671d77483de73..38de5c949ef73 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/PubSubCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/PubSubCommandsTest.java @@ -6,6 +6,7 @@ import java.time.Duration; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -16,6 +17,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.pubsub.PubSubCommands; import io.quarkus.redis.datasource.pubsub.ReactivePubSubCommands; import io.quarkus.redis.datasource.pubsub.RedisPubSubMessage; @@ -493,4 +496,26 @@ void utf8ChannelAndContent() { awaitNoMoreActiveChannels(); } + @Test + void testPubSubWithTypeReference() { + var pubsub = ds.pubsub(new TypeReference>() { + // Empty on purpose + }); + List people = new CopyOnWriteArrayList<>(); + PubSubCommands.RedisSubscriber subscriber = pubsub.subscribe(channel, map -> people.addAll(map.values())); + + pubsub.publish(channel, Map.of("luke", new Person("luke", "skywalker"))); + + Awaitility.await().until(() -> people.size() == 1); + + pubsub.publish(channel, Map.of("leia", new Person("leia", "skywalker"))); + + Awaitility.await().until(() -> people.size() == 2); + + subscriber.unsubscribe(); + + awaitNoMoreActiveChannels(); + + } + } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/SetCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/SetCommandsTest.java index 9a11440bdc311..b5d3a1d7dfafa 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/SetCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/SetCommandsTest.java @@ -12,6 +12,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.list.ListCommands; import io.quarkus.redis.datasource.set.SScanCursor; import io.quarkus.redis.datasource.set.SetCommands; @@ -333,4 +335,17 @@ void sort() { assertThat(listCommands.lpop("dest2", 100)).containsExactly("1", "2", "3", "4", "5", "6", "7", "8", "9"); } + @Test + void testSetWithTypeReference() { + var sets = ds.set(new TypeReference>() { + // Empty on purpose. + }); + assertThat(sets.sadd(key, List.of(person1, person2))).isEqualTo(1L); + assertThat(sets.sadd(key, List.of(person1, person2))).isEqualTo(0); + assertThat(sets.smembers(key)).isEqualTo(Set.of(List.of(person1, person2))); + assertThat(sets.sadd(key, List.of(person2, person3), List.of(person4))).isEqualTo(2); + assertThat(sets.smembers(key)).containsExactlyInAnyOrder(List.of(person1, person2), List.of(person2, person3), + List.of(person4)); + } + } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/SortedSetCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/SortedSetCommandsTest.java index 6f4a92d929099..b5d791247b17e 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/SortedSetCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/SortedSetCommandsTest.java @@ -16,6 +16,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.list.KeyValue; import io.quarkus.redis.datasource.list.ListCommands; import io.quarkus.redis.datasource.sortedset.Range; @@ -990,4 +992,18 @@ void sort() { assertThat(listCommands.lrange("dest1", 0, -1)).containsExactly("a", "b", "e", "f"); assertThat(listCommands.lpop("dest2", 100)).containsExactly("1", "2", "3", "4", "5", "6", "7", "8", "9"); } + + @Test + void zaddWithTypeReference() { + var set = ds.sortedSet(new TypeReference>() { + // Empty on purpose + }); + assertThat(set.zadd(key, 1.0, List.of(Place.crussol, Place.suze))).isTrue(); + assertThat(set.zadd(key, 1.0, List.of(Place.crussol, Place.suze))).isFalse(); + + assertThat(set.zrange(key, 0, -1)).isEqualTo(List.of(List.of(Place.crussol, Place.suze))); + assertThat(set.zadd(key, new ScoredValue<>(List.of(Place.grignan), 2.0), new ScoredValue<>(List.of(Place.suze), 3.0))) + .isEqualTo(2); + assertThat(set.zrange(key, 0, -1)).hasSize(3); + } } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/StreamCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/StreamCommandsTest.java index c5fc3497f5142..f79c76d565da5 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/StreamCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/StreamCommandsTest.java @@ -17,6 +17,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.stream.PendingMessage; import io.quarkus.redis.datasource.stream.StreamCommands; import io.quarkus.redis.datasource.stream.StreamMessage; @@ -767,4 +769,23 @@ void xPendingExtendedTestWithIdle() { }); } + @Test + void streamWithTypeReference() { + var stream = ds.stream(new TypeReference>() { + // Empty on purpose + }); + stream.xadd("my-stream", Map.of("duration", List.of(1532), "event-id", List.of(5), "user-id", List.of(77788))); + stream.xadd("my-stream", Map.of("duration", List.of(1533), "event-id", List.of(6), "user-id", List.of(77788))); + stream.xadd("my-stream", Map.of("duration", List.of(1534), "event-id", List.of(7), "user-id", List.of(77788))); + + List>> messages = stream.xread("my-stream", "0-0"); + assertThat(messages).hasSize(3) + .allSatisfy(m -> { + assertThat(m.key()).isEqualTo("my-stream"); + assertThat(m.id()).isNotEmpty().contains("-"); + assertThat(m.payload()).contains(entry("user-id", List.of(77788))).containsKey("event-id") + .containsKey("duration"); + }); + } + } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/TimeSeriesCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/TimeSeriesCommandsTest.java index 12524a810764b..faa980ca8b054 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/TimeSeriesCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/TimeSeriesCommandsTest.java @@ -5,12 +5,15 @@ import java.time.Duration; import java.time.temporal.ChronoUnit; +import java.util.List; import java.util.stream.Collectors; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.timeseries.AddArgs; import io.quarkus.redis.datasource.timeseries.Aggregation; import io.quarkus.redis.datasource.timeseries.AlterArgs; @@ -549,4 +552,29 @@ void testIncrementWithCreation() { assertThat(ts.tsGet(key).timestamp()).isEqualTo(1000); } + @Test + void testTimeSeriesWithTypeReference() throws InterruptedException { + var ts = ds.timeseries(new TypeReference>() { + // Empty on purpose. + }); + var key = List.of(Person.person1, Person.person2); + var key2 = List.of(Person.person0); + ts.tsCreate(key); + ts.tsCreate(key2, new CreateArgs().setRetention(Duration.of(2678400000L, ChronoUnit.MILLIS))); + + ts.tsAlter(key2, new AlterArgs().chunkSize(1024)); + + ts.tsAdd(key, 1626434637914L, 26); + ts.tsAdd(key, 27); + + Thread.sleep(1); // Do make sure we have a different timestamp + ts.tsMAdd(SeriesSample.from(key, 51), SeriesSample.from(key, 1626434637915L, 52), SeriesSample.from(key2, 22)); + + var list = ts.tsRange(key, TimeSeriesRange.fromTimeSeries()); + assertThat(list).hasSize(4); + + list = ts.tsRange(key2, TimeSeriesRange.fromTimestampToLatest(0)); + assertThat(list).hasSize(1); + } + } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/TopKCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/TopKCommandsTest.java index 0f952ff6fd29c..4c13b755dc310 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/TopKCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/TopKCommandsTest.java @@ -5,12 +5,15 @@ import static org.assertj.core.api.Assertions.entry; import java.time.Duration; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.topk.TopKCommands; import io.quarkus.redis.runtime.datasource.BlockingRedisDataSourceImpl; @@ -74,4 +77,37 @@ void creation() { assertThatThrownBy(() -> topk.topkReserve(key + "1", 20)); } + @Test + void topKWithTypeReference() { + var l1 = List.of(new Person("luke", "skywalker"), new Person("leia", "ordana")); + var l2 = List.of(new Person("leia", "ordana")); + var l3 = List.of(new Person("anakin", "skywalker")); + + var topk = ds.topk(new TypeReference>() { + // Empty on purpose + }); + + assertThatThrownBy(() -> topk.topkAdd(key, l1)) + .hasMessageContaining("TopK"); + + topk.topkReserve(key, 2); + assertThat(topk.topkAdd(key, l1)).isEmpty(); + assertThat(topk.topkAdd(key, l1)).isEmpty(); + assertThat(topk.topkAdd(key, l2)).isEmpty(); + assertThat(topk.topkAdd(key, l3)).contains(l2); + + assertThat(topk.topkAdd(key, l1, l1, l2, l2, l2, l1)).containsExactly(null, null, l3, null, null, null); + + assertThat(topk.topkList(key)).containsExactly(l1, l2); + assertThat(topk.topkListWithCount(key)).contains(entry(l1, 5), entry(l2, 4)); + + assertThat(topk.topkIncrBy(key, l3, 6)).contains(l2); + assertThat(topk.topkListWithCount(key)).contains(entry(l3, 7), entry(l1, 5)); + + assertThat(topk.topkIncrBy(key, Map.of(l2, 20, l1, 20))).hasSize(2); + assertThat(topk.topkQuery(key, l3)).isFalse(); + assertThat(topk.topkQuery(key, l1)).isTrue(); + assertThat(topk.topkQuery(key, l1, l2, l3)).containsExactly(true, true, false); + } + } diff --git a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/ValueCommandsTest.java b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/ValueCommandsTest.java index 4fab036f15263..d8b97cc798a69 100644 --- a/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/ValueCommandsTest.java +++ b/extensions/redis-client/runtime/src/test/java/io/quarkus/redis/datasource/ValueCommandsTest.java @@ -7,6 +7,7 @@ import java.time.Duration; import java.time.Instant; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Random; import java.util.UUID; @@ -15,6 +16,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.core.type.TypeReference; + import io.quarkus.redis.datasource.keys.KeyCommands; import io.quarkus.redis.datasource.value.GetExArgs; import io.quarkus.redis.datasource.value.SetArgs; @@ -297,4 +300,45 @@ void binary() { String str = cmd.get(key); assertThatThrownBy(() -> Json.decodeValue(str, byte[].class)).isInstanceOf(DecodeException.class); } + + @Test + void setWithTypeReference() { + KeyCommands keys = ds.key(String.class); + var values = ds.value(new TypeReference>() { + // Empty on purpose + }); + assertThat(values.get(key)).isNull(); + List people = List.of(Person.person1, Person.person2); + values.set(key, people); + assertThat(values.get(key)).isEqualTo(people); + + values.set(key, people, new SetArgs().px(20000)); + values.set(key, people, new SetArgs().ex(10)); + assertThat(values.get(key)).isEqualTo(people); + assertThat(keys.ttl(key)).isGreaterThanOrEqualTo(9); + + values.set(key, people, new SetArgs().ex(Duration.ofSeconds(10))); + assertThat(keys.ttl(key)).isBetween(5L, 10L); + + values.set(key, people, new SetArgs().px(Duration.ofSeconds(10))); + assertThat(keys.ttl(key)).isBetween(5L, 10L); + + values.set(key, people, new SetArgs().px(10000)); + assertThat(values.get(key)).isEqualTo(people); + assertThat(keys.ttl(key)).isGreaterThanOrEqualTo(9); + + values.set(key, people, new SetArgs().nx()); + values.set(key, people, new SetArgs().xx()); + assertThat(values.get(key)).isEqualTo(people); + + keys.del(key); + values.set(key, people, new SetArgs().nx()); + assertThat(values.get(key)).isEqualTo(people); + + keys.del(key); + + values.set(key, people, new SetArgs().px(20000).nx()); + assertThat(values.get(key)).isEqualTo(people); + assertThat(keys.ttl(key) >= 19).isTrue(); + } }