@CheckNoWriter @Test(dataProvider = "caches") @CacheSpec(loader = Loader.EXCEPTIONAL) public void get_absent_failure(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { CompletableFuture<Integer> future = cache.get(context.absentKey()); assertThat(future.isCompletedExceptionally(), is(true)); assertThat(cache.getIfPresent(context.absentKey()), is(nullValue())); }
@Test(dataProvider = "caches") @CacheSpec(population = { Population.PARTIAL, Population.FULL }, mustExpireWithAnyOf = { AFTER_WRITE, VARIABLE }, expireAfterWrite = Expire.ONE_MINUTE, expiry = { CacheExpiry.DISABLED, CacheExpiry.WRITE }, expiryTime = Expire.ONE_MINUTE) @SuppressWarnings("FutureReturnValueIgnored") public void getIfPresent(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { context.ticker().advance(30, TimeUnit.SECONDS); cache.getIfPresent(context.firstKey()); context.ticker().advance(45, TimeUnit.SECONDS); assertThat(cache.getIfPresent(context.firstKey()), is(nullValue())); assertThat(cache.getIfPresent(context.lastKey()), is(nullValue())); assertThat(cache.synchronous().estimatedSize(), is(0L)); long count = context.initialSize(); assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.EXPIRED)); }
@Test(dataProvider = "caches") @CacheSpec(mustExpireWithAnyOf = { AFTER_ACCESS, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.ACCESS }, expiryTime = Expire.ONE_MINUTE, expireAfterAccess = Expire.ONE_MINUTE, population = { Population.PARTIAL, Population.FULL }) @SuppressWarnings("FutureReturnValueIgnored") public void getIfPresent(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { context.ticker().advance(30, TimeUnit.SECONDS); cache.getIfPresent(context.firstKey()); context.ticker().advance(45, TimeUnit.SECONDS); assertThat(cache.getIfPresent(context.firstKey()), is(futureOf(-context.firstKey()))); assertThat(cache.getIfPresent(context.lastKey()), is(nullValue())); assertThat(cache.synchronous().estimatedSize(), is(1L)); long count = context.initialSize() - 1; assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.EXPIRED)); }
@CheckNoWriter @Test(dataProvider = "caches") @CacheSpec(refreshAfterWrite = Expire.ONE_MINUTE, loader = Loader.NEGATIVE, population = { Population.SINGLETON, Population.PARTIAL, Population.FULL }) public void getIfPresent(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { context.ticker().advance(30, TimeUnit.SECONDS); assertThat(cache.getIfPresent(context.middleKey()), is(futureOf(-context.middleKey()))); context.ticker().advance(45, TimeUnit.SECONDS); assertThat(cache.getIfPresent(context.middleKey()), is(futureOf(-context.middleKey()))); assertThat(cache.synchronous().estimatedSize(), is(context.initialSize())); assertThat(cache, hasRemovalNotifications(context, 1, RemovalCause.REPLACED)); }
@Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, expiryTime = Expire.ONE_MINUTE, expiry = CacheExpiry.CREATE) public void put_replace(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { CompletableFuture<Integer> future = CompletableFuture.completedFuture(context.absentValue()); context.ticker().advance(30, TimeUnit.SECONDS); cache.put(context.firstKey(), future); cache.put(context.absentKey(), future); context.consumedNotifications().clear(); // Ignore replacement notification context.ticker().advance(45, TimeUnit.SECONDS); assertThat(cache.getIfPresent(context.firstKey()), is(nullValue())); assertThat(cache.getIfPresent(context.middleKey()), is(nullValue())); assertThat(cache.getIfPresent(context.absentKey()), is(futureOf(context.absentValue()))); assertThat(cache.synchronous().estimatedSize(), is(1L)); long count = context.initialSize(); assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.EXPIRED)); verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.EXPIRED)); }
@Test(dataProvider = "caches") @CacheSpec(population = Population.EMPTY, expiryTime = Expire.ONE_MINUTE, mustExpireWithAnyOf = { AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.WRITE }, expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) @SuppressWarnings("FutureReturnValueIgnored") public void get_writeTime(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { Integer key = context.absentKey(); Integer value = context.absentValue(); cache.get(key, k -> { context.ticker().advance(5, TimeUnit.MINUTES); return value; }); assertThat(cache.synchronous().estimatedSize(), is(1L)); assertThat(cache.getIfPresent(key), futureOf(value)); }
@Test(dataProvider = "caches") @CacheSpec(population = Population.FULL, expiryTime = Expire.ONE_MINUTE, mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) public void put_replace(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { CompletableFuture<Integer> future = CompletableFuture.completedFuture(context.absentValue()); context.ticker().advance(30, TimeUnit.SECONDS); cache.put(context.firstKey(), future); cache.put(context.absentKey(), future); context.consumedNotifications().clear(); // Ignore replacement notification context.ticker().advance(45, TimeUnit.SECONDS); assertThat(cache.getIfPresent(context.firstKey()), is(futureOf(context.absentValue()))); assertThat(cache.getIfPresent(context.absentKey()), is(futureOf(context.absentValue()))); assertThat(cache.getIfPresent(context.middleKey()), is(nullValue())); assertThat(cache.synchronous().estimatedSize(), is(2L)); long count = context.initialSize() - 1; assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.EXPIRED)); verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.EXPIRED)); }
@Test(dataProvider = "caches") @CacheSpec(population = Population.EMPTY, removalListener = Listener.CONSUMING, mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) @SuppressWarnings("FutureReturnValueIgnored") public void get_async(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { CompletableFuture<Integer> future = new CompletableFuture<Integer>(); cache.get(context.absentKey(), (k, e) -> future); context.ticker().advance(2, TimeUnit.MINUTES); cache.synchronous().cleanUp(); assertThat(cache, hasRemovalNotifications(context, 0, RemovalCause.EXPIRED)); future.complete(context.absentValue()); context.ticker().advance(30, TimeUnit.SECONDS); assertThat(cache.getIfPresent(context.absentKey()), is(future)); context.ticker().advance(1, TimeUnit.MINUTES); assertThat(cache.getIfPresent(context.absentKey()), is(nullValue())); cache.synchronous().cleanUp(); assertThat(cache, hasRemovalNotifications(context, 1, RemovalCause.EXPIRED)); verifyWriter(context, (verifier, writer) -> verifier.deletions(1, RemovalCause.EXPIRED)); }
@Test(dataProvider = "caches") @CacheSpec(population = Population.EMPTY, removalListener = Listener.CONSUMING, mustExpireWithAnyOf = { AFTER_ACCESS, AFTER_WRITE, VARIABLE }, expiry = { CacheExpiry.DISABLED, CacheExpiry.CREATE, CacheExpiry.WRITE, CacheExpiry.ACCESS }, expireAfterAccess = {Expire.DISABLED, Expire.ONE_MINUTE}, expiryTime = Expire.ONE_MINUTE, expireAfterWrite = {Expire.DISABLED, Expire.ONE_MINUTE}) @SuppressWarnings("FutureReturnValueIgnored") public void put_insert_async(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { CompletableFuture<Integer> future = new CompletableFuture<Integer>(); cache.put(context.absentKey(), future); context.ticker().advance(2, TimeUnit.MINUTES); cache.synchronous().cleanUp(); assertThat(cache, hasRemovalNotifications(context, 0, RemovalCause.EXPIRED)); future.complete(context.absentValue()); context.ticker().advance(30, TimeUnit.SECONDS); assertThat(cache.getIfPresent(context.absentKey()), is(future)); context.ticker().advance(1, TimeUnit.MINUTES); assertThat(cache.getIfPresent(context.absentKey()), is(nullValue())); cache.synchronous().cleanUp(); assertThat(cache, hasRemovalNotifications(context, 1, RemovalCause.EXPIRED)); verifyWriter(context, (verifier, writer) -> verifier.deletions(1, RemovalCause.EXPIRED)); }
@CheckNoWriter @Test(dataProvider = "caches") @CacheSpec(loader = Loader.EXCEPTIONAL, executor = CacheExecutor.THREADED, executorFailure = ExecutorFailure.IGNORED) public void get_absent_failure_async(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) throws InterruptedException { AtomicBoolean done = new AtomicBoolean(); Integer key = context.absentKey(); CompletableFuture<Integer> valueFuture = cache.get(key); valueFuture.whenComplete((r, e) -> done.set(true)); Awaits.await().untilTrue(done); Awaits.await().until(() -> !cache.synchronous().asMap().containsKey(context.absentKey())); Awaits.await().until(() -> context, both(hasMissCount(1)).and(hasHitCount(0))); Awaits.await().until(() -> context, both(hasLoadSuccessCount(0)).and(hasLoadFailureCount(1))); assertThat(valueFuture.isCompletedExceptionally(), is(true)); assertThat(cache.getIfPresent(key), is(nullValue())); }
@CheckNoWriter @Test(dataProvider = "caches") @CacheSpec(refreshAfterWrite = Expire.ONE_MINUTE, population = { Population.PARTIAL, Population.FULL }) @SuppressWarnings("FutureReturnValueIgnored") public void get(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) { context.ticker().advance(30, TimeUnit.SECONDS); cache.get(context.firstKey()); cache.get(context.absentKey()); context.ticker().advance(45, TimeUnit.SECONDS); assertThat(cache.getIfPresent(context.firstKey()), is(futureOf(-context.firstKey()))); assertThat(cache, hasRemovalNotifications(context, 1, RemovalCause.REPLACED)); }
@SuppressWarnings("unchecked") public <T> T getDataIfPresent(String path) { return (T) dataCache.getIfPresent(path); }
@Override public CompletableFuture<Optional<V>> getIfPresent(final K key) { requireNonNull(key); final CompletableFuture<V> future = asyncLoadingCache.getIfPresent(key); return future == null ? CompletableFuture.completedFuture(Optional.empty()) : future.thenApply(Optional::ofNullable); }
@Override public CompletableFuture<Optional<UserAgentIngredients>> read(String raw) { return Optional.ofNullable(caffeine.getIfPresent(raw)) .map(future -> future.thenApply(Optional::ofNullable)) .orElse(CompletableFuture.completedFuture(Optional.empty())); }
@Override public boolean invalidate(final K key) { requireNonNull(key); final boolean currentlyExisting = asyncLoadingCache.getIfPresent(key) != null; final boolean reportInvalidation = (metricStatsCounter != null) && currentlyExisting; synchronousCacheView.invalidate(key); if (reportInvalidation) { metricStatsCounter.recordInvalidation(); } return currentlyExisting; }
/** * Return the {@link OwnedBundle} instance from the local cache. Does not block. * * @param bundle * @return */ public OwnedBundle getOwnedBundle(NamespaceBundle bundle) { CompletableFuture<OwnedBundle> future = ownedBundlesCache.getIfPresent(ServiceUnitZkUtils.path(bundle)); if (future != null && future.isDone() && !future.isCompletedExceptionally()) { return future.join(); } else { return null; } }
/** * Return the {@link OwnedBundle} instance from the local cache. Does not block. * * @param bundle * @return */ public OwnedBundle getOwnedBundle(NamespaceBundle bundle) { CompletableFuture<OwnedBundle> future = ownedBundlesCache.getIfPresent(ServiceUnitZkUtils.path(bundle)); if (future != null && future.isDone() && !future.isCompletedExceptionally()) { return future.join(); } else { return null; } }
/** * Update bundle state in a local cache * * @param bundle * @throws Exception */ public void updateBundleState(NamespaceBundle bundle, boolean isActive) throws Exception { String path = ServiceUnitZkUtils.path(bundle); // Disable owned instance in local cache CompletableFuture<OwnedBundle> f = ownedBundlesCache.getIfPresent(path); if (f != null && f.isDone() && !f.isCompletedExceptionally()) { f.join().setActive(isActive); } }
/** * Update bundle state in a local cache * * @param bundle * @throws Exception */ public void updateBundleState(NamespaceBundle bundle, boolean isActive) throws Exception { String path = ServiceUnitZkUtils.path(bundle); // Disable owned instance in local cache CompletableFuture<OwnedBundle> f = ownedBundlesCache.getIfPresent(path); if (f != null && f.isDone() && !f.isCompletedExceptionally()) { f.join().setActive(isActive); } }
@Override public boolean invalidate(final K key) { requireNonNull(key); final boolean currentlyExisting = asyncLoadingCache.getIfPresent(key) != null; synchronousCacheView.invalidate(key); if (metricStatsCounter != null) { if (currentlyExisting) { metricStatsCounter.recordInvalidation(); } else { metricStatsCounter.recordInvalidationWithoutItem(); } } return currentlyExisting; }