Skip to content

Commit

Permalink
Cache a placeholder instead of a wrapper Uni
Browse files Browse the repository at this point in the history
  • Loading branch information
gwenneg committed Apr 19, 2021
1 parent 85ac88b commit 35d60d7
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,21 @@ public class UniValueTest {
public void test() {
// STEP 1
// Action: a method annotated with @CacheResult and returning a Uni is called.
// Expected effect: the method is invoked and its result is wrapped into an UnresolvedUniValue which is cached.
// Expected effect: the method is invoked and an UnresolvedUniValue is cached.
// Verified by: invocations counter and CacheResultInterceptor log.
Uni<String> uni1 = cachedService.cachedMethod(KEY);
assertEquals(1, cachedService.getInvocations());

// STEP 2
// Action: same call as STEP 1.
// Expected effect: the method is NOT invoked and the cached UnresolvedUniValue from STEP 1 is used to produce a result.
// Expected effect: the method is invoked because the key is associated with a cached UnresolvedUniValue.
// Verified by: invocations counter and CacheResultInterceptor log.
Uni<String> uni2 = cachedService.cachedMethod(KEY);
assertEquals(1, cachedService.getInvocations());
assertEquals(2, cachedService.getInvocations());

// STEP 3
// Action: the Uni returned in STEP 1 is subscribed to and we wait for an item event to be fired.
// Expected effect: the UnresolvedUniValue wrapper cached during STEP 1 is replaced with the emitted item from this step in the cache.
// Expected effect: the UnresolvedUniValue cached during STEP 1 is replaced with the emitted item from this step in the cache.
// Verified by: subscriptions counter and CaffeineCache log.
String emittedItem1 = uni1.await().indefinitely();
assertEquals("1", emittedItem1); // This checks the subscriptions counter value.
Expand All @@ -67,16 +67,16 @@ public void test() {
// Expected effect: the method is not invoked and the emitted item cached during STEP 4 is returned.
// Verified by: invocations and subscriptions counters, same object reference between STEPS 4 and 5 emitted items.
String emittedItem3 = cachedService.cachedMethod(KEY).await().indefinitely();
assertEquals(1, cachedService.getInvocations());
assertEquals(2, cachedService.getInvocations());
assertEquals("2", emittedItem3); // This checks the subscriptions counter value.
assertTrue(emittedItem2 == emittedItem3);

// STEP 6
// Action: same call as STEP 5 with a different key.
// Expected effect: the method is invoked, its result is wrapped into an UnresolvedUniValue which is cached.
// Expected effect: the method is invoked and an UnresolvedUniValue is cached.
// Verified by: invocations and subscriptions counters, CacheResultInterceptor log and different objects references between STEPS 5 and 6 emitted items.
String emittedItem4 = cachedService.cachedMethod("another-key").await().indefinitely();
assertEquals(2, cachedService.getInvocations());
assertEquals(3, cachedService.getInvocations());
assertEquals("3", emittedItem4); // This checks the subscriptions counter value.
assertTrue(emittedItem3 != emittedItem4);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,12 @@ public Object intercept(InvocationContext invocationContext) throws Throwable {
@Override
public Object apply(Object k) {
try {
Object invocationResult = invocationContext.proceed();
if (invocationResult instanceof Uni) {
if (Uni.class.isAssignableFrom(invocationContext.getMethod().getReturnType())) {
LOGGER.debugf("Adding %s entry with key [%s] into cache [%s]",
UnresolvedUniValue.class.getSimpleName(), key, cache.getName());
return new UnresolvedUniValue((Uni<Object>) invocationResult);
return new UnresolvedUniValue();
} else {
return invocationResult;
return invocationContext.proceed();
}
} catch (Exception e) {
throw new CacheException(e);
Expand All @@ -79,7 +78,7 @@ public Object apply(Object k) {
}

if (Uni.class.isAssignableFrom(invocationContext.getMethod().getReturnType())) {
return unwrapUniValue(cache, key, value);
return resolveUni(invocationContext, cache, key, value);
} else {
return value;
}
Expand Down Expand Up @@ -109,12 +108,12 @@ public Object apply(Object k) {
}
}

private Object unwrapUniValue(AbstractCache cache, Object key, Object value) {
private Object resolveUni(InvocationContext invocationContext, AbstractCache cache, Object key, Object value)
throws Exception {
if (value instanceof UnresolvedUniValue) {
UnresolvedUniValue unresolvedUniValue = (UnresolvedUniValue) value;
return unresolvedUniValue.getUni()
return ((Uni<Object>) invocationContext.proceed())
.onItem().call(emittedValue -> cache.replaceUniValue(key, emittedValue))
.onFailure().call(() -> cache.removeUnresolvedUniValue(key, unresolvedUniValue));
.onFailure().call(() -> cache.removeUnresolvedUniValue(key, (UnresolvedUniValue) value));
} else {
return Uni.createFrom().item(value);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
package io.quarkus.cache.runtime;

import io.smallrye.mutiny.Uni;

/**
* This value acts as a placeholder in the cache. It will be eventually replaced by the item emitted by the
* {@link io.smallrye.mutiny.Uni Uni} when it has been resolved.
*/
public class UnresolvedUniValue {

private final Uni<Object> uni;

public UnresolvedUniValue(Uni<Object> uni) {
this.uni = uni;
}

public Uni<Object> getUni() {
return uni;
}
}

0 comments on commit 35d60d7

Please sign in to comment.