Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis Cache - Allow usage of cache name when prefix is defined #44856

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions docs/src/main/asciidoc/cache-redis-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ include::{includes}/extension-status.adoc[]
When using Redis as the backend for Quarkus cache, each cached item will be stored in Redis:

- The backend uses the _<default>_ Redis client (if not configured otherwise), so make sure it's configured (or use the xref:redis-dev-services.adoc[Redis Dev Service])
- the Redis key is built as follows: `cache:$cache-name:$cache-key`, where `cache-key` is the key the application uses.
- the Redis key is built as follows: `cache:{cache-name}:{cache-key}`, where `cache-key` is the key the application uses and `cache:{cache-name}` the prefix.
- the value is encoded to JSON if needed


Expand Down Expand Up @@ -118,10 +118,11 @@ include::{generated-dir}/config/quarkus-redis-cache.adoc[opts=optional, leveloff

== Configure the Redis key

By default, the Redis backend stores the entry using the following keys: `cache:$cache-name:$cache-key`, where `cache-key` is the key the application uses.
So, you can find all the entries for a single cache using the Redis `KEYS` command: `KEYS cache:$cache-name:*`
By default, the Redis backend stores the entry using the following keys pattern: `cache:{cache-name}:{cache-key}`, where `cache-key` is the key the application uses and `cache:{cache-name}` the prefix. The variable `{cache-name}` is resolved from the value set in the cache annotations.
So, you can find all the entries for a single cache using the Redis `KEYS` command: `KEYS cache:{cache-name}:*`

The prefix can be configured by using the `prefix` property:

The `cache:$cache-name:` segment can be configured using the `prefix` property:


[source, properties]
Expand All @@ -135,6 +136,16 @@ quarkus.cache.redis.expensiveResourceCache.prefix=my-expensive-cache

In these cases, you can find all the keys managed by the default cache using `KEYS my-cache:*`, and all the keys managed by the `expensiveResourceCache` cache using: `KEYS my-expensive-cache:*`.


----
# Default configuration
# The variable "{cache-name}" is resolved from the value set in the cache annotations.
quarkus.cache.redis.prefix=my-cache-{cache-name}
----

In this latest example, you can find all the keys managed by the default cache using `KEYS my-cache-{cache-name}:*`.


== Enable optimistic locking

The access to the cache can be _direct_ or use https://redis.io/docs/manual/transactions/#optimistic-locking-using-check-and-set[optimistic locking].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,15 +397,11 @@ public Uni<?> apply(List<String> listOfKeys) {
}

String computeActualKey(String key) {
if (cacheInfo.prefix != null) {
return cacheInfo.prefix + ":" + key;
} else {
return "cache:" + getName() + ":" + key;
}
return getKeyPrefix() + ":" + key;
}

Object computeUserKey(String key) {
String prefix = cacheInfo.prefix != null ? cacheInfo.prefix : "cache:" + getName();
String prefix = getKeyPrefix();
if (!key.startsWith(prefix + ":")) {
return null; // Not a key handle by the cache.
}
Expand All @@ -414,10 +410,14 @@ Object computeUserKey(String key) {
}

private String getKeyPattern() {
return getKeyPrefix() + ":*";
}

private String getKeyPrefix() {
if (cacheInfo.prefix != null) {
return cacheInfo.prefix + ":" + "*";
return cacheInfo.prefix.replace("{cache-name}", getName());
} else {
return "cache:" + getName() + ":" + "*";
return "cache:" + getName();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ public class RedisCacheRuntimeConfig {
Optional<Duration> expireAfterAccess;

/**
* the key prefix allowing to identify the keys belonging to the cache.
* If not set, use "cache:$cache-name"
* The key prefix allowing to identify the keys belonging to the cache.
* If not set, the value "{@code cache:{cache-name}}" will be used. The variable
* "{@code {cache-name}}" is resolved from the value set in the cache annotations.
*/
@ConfigItem
public Optional<String> prefix;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,39 @@ void clear() {
}
}

@Test
public void testComputeActualKey() {
RedisCacheInfo info = new RedisCacheInfo();
info.name = "foo";
info.prefix = null;
info.expireAfterWrite = Optional.of(Duration.ofSeconds(2));

RedisCacheImpl cache = new RedisCacheImpl(info, vertx, redis, BLOCKING_ALLOWED);
assertThat(cache.computeActualKey("keyname")).isEqualTo("cache:foo:keyname");
}

@Test
public void testComputeActualKeyWithCustomPrefix() {
RedisCacheInfo info = new RedisCacheInfo();
info.name = "foo";
info.prefix = "my-prefix";
info.expireAfterWrite = Optional.of(Duration.ofSeconds(2));

RedisCacheImpl cache = new RedisCacheImpl(info, vertx, redis, BLOCKING_ALLOWED);
assertThat(cache.computeActualKey("keyname")).isEqualTo("my-prefix:keyname");
}

@Test
public void testComputeActualKeyWithCustomPrefixUsingCacheNameVariable() {
RedisCacheInfo info = new RedisCacheInfo();
info.name = "foo";
info.prefix = "my-prefix:{cache-name}";
info.expireAfterWrite = Optional.of(Duration.ofSeconds(2));

RedisCacheImpl cache = new RedisCacheImpl(info, vertx, redis, BLOCKING_ALLOWED);
assertThat(cache.computeActualKey("keyname")).isEqualTo("my-prefix:foo:keyname");
}

@Test
public void testPutInTheCache() {
String k = UUID.randomUUID().toString();
Expand Down
Loading