-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Closed
Description
Maybe this has come up before, but this seems a bit odd. Here is my test.
@RunWith(JUnit4.class)
public final class AsyncLoadingCacheTest {
private final AtomicLong counter = new AtomicLong(0);
private final FakeTicker ticker = new FakeTicker();
private ListenableFutureTask<Long> loadingTask;
private final AsyncCacheLoader<String, Long> loader =
(key, exec) ->
// Fools the cache into thinking there is a future that's not immediately ready.
// (The Cache has optimizations for this that we want to avoid)
toCompletableFuture(loadingTask = ListenableFutureTask.create(counter::getAndIncrement));
private final String key = AsyncLoadingCacheTest.class.getSimpleName();
/** This ensures that any outstanding async loading is completed as well */
private long loadGet(AsyncLoadingCache<String, Long> cache, String key)
throws InterruptedException, ExecutionException {
CompletableFuture<Long> future = cache.get(key);
if (!loadingTask.isDone()) {
loadingTask.run();
}
return future.get();
}
@Test
public void invalidateDuringRefreshRemovalCheck() throws Exception {
List<Long> removed = new ArrayList<>();
AsyncLoadingCache<String, Long> cache =
Caffeine.newBuilder()
.ticker(ticker)
.executor(TestingExecutors.sameThreadScheduledExecutor())
.<String, Long>removalListener((key, value, reason) -> removed.add(value))
.refreshAfterWrite(10, TimeUnit.NANOSECONDS)
.buildAsync(loader);
// Load so there is an initial value.
assertThat(loadGet(cache, key)).isEqualTo(0);
ticker.advance(11); // Refresh should fire on next access
assertThat(cache.synchronous().getIfPresent(key)).isEqualTo(0L); // Old value
cache.synchronous().invalidate(key); // Invalidate key entirely
assertThat(cache.synchronous().getIfPresent(key)).isNull(); // No value in cache (good)
loadingTask.run(); // Completes refresh
// FIXME: java.lang.AssertionError: Not true that <1> is null
assertThat(cache.synchronous().getIfPresent(key)).isNull(); // Value in cache (bad)
// FIXME: Maybe? This is what I wanted to actually test :)
assertThat(removed).containsExactly(0L, 1L); // 1L was sent to removalListener anyways
}
}It would appear that a refresh that started before an invalidate takes precedence over the invalidate? What I really wanted to test was the removal listener, but I ran into this first.
I'm using Caffeine 2.5.3
Thanks again for your good work.
Metadata
Metadata
Assignees
Labels
No labels