Skip to content

Commit

Permalink
Redis Cache: improve the API consistency
Browse files Browse the repository at this point in the history
All the `get*` methods in the `RedisCache` API now have 3 variants:

- not accepting value type, using the configured default
- accepting value type as a `Class`
- accepting value type as a `TypeLiteral`

Internally, all these methods delegate to an implementation
that takes a `Type`.

The error message about the default value type was also consolidated
into a single place, the `enforceDefaultType()` method.
  • Loading branch information
Ladicek committed Sep 24, 2024
1 parent 3baeed1 commit 640f169
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ public interface RedisCache extends Cache {

/**
* When configured, gets the default type of the value stored in the cache.
* The configured type is used when no type is passed into the {@link #get(Object, Class, Function)}.
* The configured type is used in methods {@link #get(Object, Function)},
* {@link #getAsync(Object, Function)}, {@link #getOrDefault(Object, Object)}
* and {@link #getOrNull(Object)}.
*
* @deprecated should have never been exposed publicly
* @return the type, {@code null} if not configured or if not a {@code Class}.
Expand Down Expand Up @@ -83,20 +85,89 @@ public interface RedisCache extends Cache {
* @param <V> the type of value
* @return a Uni emitting {@code null} when the operation completes
*/
default <K, V> Uni<Void> put(K key, V value) {
return put(key, new Supplier<V>() {
@Override
public V get() {
return value;
}
});
}
<K, V> Uni<Void> put(K key, V value);

/**
* Put a value in the cache.
*
* @param key the key
* @param supplier supplier of the value
* @param <K> the type of key
* @param <V> the type of value
* @return a Uni emitting {@code null} when the operation completes
*/
<K, V> Uni<Void> put(K key, Supplier<V> supplier);

/**
* Returns {@link Uni} that completes with a value present in the cache under the given {@code key}.
* If there is no value in the cache under the key, the {@code Uni} completes with the given {@code defaultValue}.
*
* @param key the key
* @param defaultValue the default value
* @param <K> the type of key
* @param <V> the type of value
* @return a Uni emitting the value cached under {@code key}, or {@code defaultValue} if there is no cached value
*/
<K, V> Uni<V> getOrDefault(K key, V defaultValue);

/**
* Returns {@link Uni} that completes with a value present in the cache under the given {@code key}.
* If there is no value in the cache under the key, the {@code Uni} completes with the given {@code defaultValue}.
*
* @param key the key
* @param clazz class of the value
* @param defaultValue the default value
* @param <K> the type of key
* @param <V> the type of value
* @return a Uni emitting the value cached under {@code key}, or {@code defaultValue} if there is no cached value
*/
<K, V> Uni<V> getOrDefault(K key, Class<V> clazz, V defaultValue);

/**
* Returns {@link Uni} that completes with a value present in the cache under the given {@code key}.
* If there is no value in the cache under the key, the {@code Uni} completes with the given {@code defaultValue}.
*
* @param key the key
* @param type type of the value
* @param defaultValue the default value
* @param <K> the type of key
* @param <V> the type of value
* @return a Uni emitting the value cached under {@code key}, or {@code defaultValue} if there is no cached value
*/
<K, V> Uni<V> getOrDefault(K key, TypeLiteral<V> type, V defaultValue);

/**
* Returns {@link Uni} that completes with a value present in the cache under the given {@code key}.
* If there is no value in the cache under the key, the {@code Uni} completes with {@code null}.
*
* @param key the key
* @param <K> the type of key
* @param <V> the type of value
* @return a Uni emitting the value cached under {@code key}, or {@code null} if there is no cached value
*/
<K, V> Uni<V> getOrNull(K key);

/**
* Returns {@link Uni} that completes with a value present in the cache under the given {@code key}.
* If there is no value in the cache under the key, the {@code Uni} completes with {@code null}.
*
* @param key the key
* @param clazz the class of the value
* @param <K> the type of key
* @param <V> the type of value
* @return a Uni emitting the value cached under {@code key}, or {@code null} if there is no cached value
*/
<K, V> Uni<V> getOrNull(K key, Class<V> clazz);

/**
* Returns {@link Uni} that completes with a value present in the cache under the given {@code key}.
* If there is no value in the cache under the key, the {@code Uni} completes with {@code null}.
*
* @param key the key
* @param type the type of the value
* @param <K> the type of key
* @param <V> the type of value
* @return a Uni emitting the value cached under {@code key}, or {@code null} if there is no cached value
*/
<K, V> Uni<V> getOrNull(K key, TypeLiteral<V> type);
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,7 @@ public V get() {

@Override
public <K, V> Uni<V> get(K key, Function<K, V> valueLoader) {
if (classOfValue == null) {
throw new UnsupportedOperationException("Cannot use `get` method without a default type configured. "
+ "Consider using the `get` method accepting the type or configure the default type for the cache "
+ getName());
}
enforceDefaultType("get");
return get(key, classOfValue, valueLoader);
}

Expand Down Expand Up @@ -224,11 +220,7 @@ public Uni<? extends V> apply(Throwable e) {

@Override
public <K, V> Uni<V> getAsync(K key, Function<K, Uni<V>> valueLoader) {
if (classOfValue == null) {
throw new UnsupportedOperationException("Cannot use `getAsync` method without a default type configured. "
+ "Consider using the `getAsync` method accepting the type or configure the default type for the cache "
+ getName());
}
enforceDefaultType("getAsync");
return getAsync(key, classOfValue, valueLoader);
}

Expand Down Expand Up @@ -304,25 +296,46 @@ public Uni<Void> apply(RedisConnection connection) {
});
}

private void enforceDefaultType() {
private void enforceDefaultType(String methodName) {
if (classOfValue == null) {
throw new UnsupportedOperationException(
"Cannot execute the operation without the default type configured in cache " + cacheInfo.name);
throw new UnsupportedOperationException("Cannot use `" + methodName + "` method without a default type configured. "
+ "Consider using the `" + methodName + "` method accepting the type or configure the default type for the cache "
+ getName());
}
}

@Override
public <K, V> Uni<V> getOrDefault(K key, V defaultValue) {
enforceDefaultType();
enforceDefaultType("getOrDefault");
return getOrDefault(key, classOfValue, defaultValue);
}

@Override
public <K, V> Uni<V> getOrDefault(K key, Class<V> clazz, V defaultValue) {
return getOrDefault(key, (Type) clazz, defaultValue);
}

@Override
public <K, V> Uni<V> getOrDefault(K key, TypeLiteral<V> type, V defaultValue) {
return getOrDefault(key, type.getType(), defaultValue);
}

private <K, V> Uni<V> getOrDefault(K key, Type type, V defaultValue) {
byte[] encodedKey = marshaller.encode(computeActualKey(encodeKey(key)));
return withConnection(new Function<RedisConnection, Uni<V>>() {
@Override
public Uni<V> apply(RedisConnection redisConnection) {
return doGet(redisConnection, encodedKey, classOfValue, marshaller);
return doGet(redisConnection, encodedKey, type, marshaller);
}
}).onItem().ifNull().continueWith(new StaticSupplier<>(defaultValue));
}

@Override
public <K, V> Uni<V> getOrNull(K key) {
enforceDefaultType("getOrNull");
return getOrNull(key, classOfValue);
}

@Override
public <K, V> Uni<V> getOrNull(K key, Class<V> clazz) {
return getOrNull(key, (Type) clazz);
Expand All @@ -334,13 +347,11 @@ public <K, V> Uni<V> getOrNull(K key, TypeLiteral<V> type) {
}

private <K, V> Uni<V> getOrNull(K key, Type type) {
enforceDefaultType();
byte[] encodedKey = marshaller.encode(computeActualKey(encodeKey(key)));
return withConnection(new Function<RedisConnection, Uni<V>>() {
@Override
public Uni<V> apply(RedisConnection redisConnection) {
// TODO maybe use `type` (if non-null?) instead of `classOfValue`?
return doGet(redisConnection, encodedKey, classOfValue, marshaller);
return doGet(redisConnection, encodedKey, type, marshaller);
}
});
}
Expand Down

0 comments on commit 640f169

Please sign in to comment.