Skip to content

Commit

Permalink
added config to control the behavior of check on null values
Browse files Browse the repository at this point in the history
  • Loading branch information
anadinema committed Aug 5, 2024
1 parent b5231da commit 5a2d66a
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 1 deletion.
16 changes: 16 additions & 0 deletions docs/src/main/asciidoc/cache-redis-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,19 @@ quarkus.cache.redis.expensiveResourceCache.use-optimistic-locking=true
----

When used, the key is _watched_ and the _SET_ command is executed in a transaction (`MULTI/EXEC`).

== Ignore the null values

As redis does not support saving null values in cache, so if the return type of method annotated with `@CacheResult`, then a `IllegalArgumentException` is thrown to prevent it from being saved in cache.
However, if you want to safely ignore that return value and treat it as cache miss, then you use choose to ignore those null values.
By default, this behavior is disabled, and the values will be checked.

You can choose to ignore null values using:
[source, properties]
----
# Default configuration
quarkus.cache.redis.ignore-null-value=true
# Configuration for `expensiveResourceCache`
quarkus.cache.redis.expensiveResourceCache.ignore-null-value=true
----
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ public Uni<V> apply(V cached) throws Exception {
@Override
public Uni<?> apply(V value) {
if (value == null) {
if (cacheInfo.ignoreNullValue) {
return Uni.createFrom().nullItem();
}
throw new IllegalArgumentException("Cannot cache `null` value");
}
byte[] encodedValue = marshaller.encode(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,10 @@ public class RedisCacheInfo {
* Locking</a> for details.
*/
public boolean useOptimisticLocking = false;

/**
* Specifies whether to safely ignore the calls when trying to save {@code null} in cache.
* If not set, then values will be checked, and {@code IllegalArgumentException} is thrown for null values.
*/
public boolean ignoreNullValue = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ public static Set<RedisCacheInfo> build(Set<String> cacheNames, RedisCachesBuild
cacheInfo.useOptimisticLocking = defaultRuntimeConfig.useOptimisticLocking.get();
}

if (namedRuntimeConfig != null && namedRuntimeConfig.ignoreNullValue.isPresent()) {
cacheInfo.ignoreNullValue = namedRuntimeConfig.ignoreNullValue.get();
} else if (defaultRuntimeConfig.ignoreNullValue.isPresent()) {
cacheInfo.ignoreNullValue = defaultRuntimeConfig.ignoreNullValue.get();
}

result.add(cacheInfo);
}
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,12 @@ public class RedisCacheRuntimeConfig {
@ConfigItem
public Optional<Boolean> useOptimisticLocking;

/**
* Specifies whether to safely ignore the calls when trying to save {@code null} in cache.
* If not set, then values will be checked, and {@code IllegalArgumentException} is thrown for null values.
* Default is {@code false}.
*/
@ConfigItem
public Optional<Boolean> ignoreNullValue;

}
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ public void testGetOrDefault() {
}

@Test
public void testCacheNullValue() {
public void testCacheNullValueWithoutIgnoringNullValue() {
RedisCacheInfo info = new RedisCacheInfo();
info.expireAfterWrite = Optional.of(Duration.ofSeconds(10));
info.valueType = Person.class.getName();
Expand All @@ -244,6 +244,20 @@ public void testCacheNullValue() {
assertThatTheKeyDoesNotExist("cache:default-redis-cache:" + Json.encode(key));
}

@Test
public void testCacheNullValueWithIgnoringNullValue() {
RedisCacheInfo info = new RedisCacheInfo();
info.expireAfterWrite = Optional.of(Duration.ofSeconds(10));
info.valueType = Person.class.getName();
info.ignoreNullValue = true;
RedisCacheImpl cache = new RedisCacheImpl(info, vertx, redis, BLOCKING_ALLOWED);

// with custom key
double key = 122334545.0;
assertThat(cache.get(key, k -> null).await().indefinitely()).isNull();
assertThatTheKeyDoesNotExist("cache:default-redis-cache:" + Json.encode(key));
}

@Test
public void testExceptionInValueLoader() {
RedisCacheInfo info = new RedisCacheInfo();
Expand Down

0 comments on commit 5a2d66a

Please sign in to comment.