@Test public void testReloadFailedGets() throws Exception { AsyncLoadingCache<String, Integer> cachedResult = new AsyncLoadingCache<>(250); AtomicInteger counter1 = new AtomicInteger(); AtomicInteger counter2 = new AtomicInteger(); for (int i = 1; i <= 3; i++) { assertThat(cachedResult.orElseGet("k1", getSupplier(234, counter1, false)).join(), is(234)); assertThat("we do not call the supplier while the cache is valid", counter1.get(), is(1)); assertThrows(CompletionException.class, () -> cachedResult.orElseGet("k2", getSupplier(987, counter2, true)).join()); assertThat("we retry the supplier after a failure", counter2.get(), is(i)); } }
@SuppressWarnings("squid:S2789") @Nonnull public CompletableFuture<V> orElseGet(@Nonnull K key, @Nonnull Supplier<CompletableFuture<V>> supplier) { try { Optional<V> cachedValue = cache.getIfPresent(key); if (cachedValue == null) { return MoreAsyncUtil.getWithDeadline(deadlineTimeMillis, supplier).thenApply(value -> { final Optional<V> existingValue = cache.asMap().putIfAbsent(key, Optional.ofNullable(value)); return existingValue == null ? value : existingValue.orElse(null); }); } else { return CompletableFuture.completedFuture(cachedValue.orElse(null)); } } catch (Exception e) { throw new RecordCoreException("failed getting value", e).addLogInfo("cacheKey", key); } }
AsyncLoadingCache { @SuppressWarnings("squid:S2789") @Nonnull public CompletableFuture<V> orElseGet(@Nonnull K key, @Nonnull Supplier<CompletableFuture<V>> supplier) { try { Optional<V> cachedValue = cache.getIfPresent(key); if (cachedValue == null) { return MoreAsyncUtil.getWithDeadline(deadlineTimeMillis, supplier).thenApply(value -> { final Optional<V> existingValue = cache.asMap().putIfAbsent(key, Optional.ofNullable(value)); return existingValue == null ? value : existingValue.orElse(null); }); } else { return CompletableFuture.completedFuture(cachedValue.orElse(null)); } } catch (Exception e) { throw new RecordCoreException("failed getting value", e).addLogInfo("cacheKey", key); } } }
AsyncLoadingCache { @SuppressWarnings("squid:S2789") @Nonnull public CompletableFuture<V> orElseGet(@Nonnull K key, @Nonnull Supplier<CompletableFuture<V>> supplier) { try { Optional<V> cachedValue = cache.getIfPresent(key); if (cachedValue == null) { return MoreAsyncUtil.getWithDeadline(deadlineTimeMillis, supplier).thenApply(value -> { final Optional<V> existingValue = cache.asMap().putIfAbsent(key, Optional.ofNullable(value)); return existingValue == null ? value : existingValue.orElse(null); }); } else { return CompletableFuture.completedFuture(cachedValue.orElse(null)); } } catch (Exception e) { throw new RecordCoreException("failed getting value", e).addLogInfo("cacheKey", key); } } AsyncLoadingCache(long refreshTimeMillis);  AsyncLoadingCache(long refreshTimeMillis, long deadlineTimeMillis);  AsyncLoadingCache(long refreshTimeMillis, long deadlineTimeMillis, long maxSize); }
AsyncLoadingCache { @SuppressWarnings("squid:S2789") @Nonnull public CompletableFuture<V> orElseGet(@Nonnull K key, @Nonnull Supplier<CompletableFuture<V>> supplier) { try { Optional<V> cachedValue = cache.getIfPresent(key); if (cachedValue == null) { return MoreAsyncUtil.getWithDeadline(deadlineTimeMillis, supplier).thenApply(value -> { final Optional<V> existingValue = cache.asMap().putIfAbsent(key, Optional.ofNullable(value)); return existingValue == null ? value : existingValue.orElse(null); }); } else { return CompletableFuture.completedFuture(cachedValue.orElse(null)); } } catch (Exception e) { throw new RecordCoreException("failed getting value", e).addLogInfo("cacheKey", key); } } AsyncLoadingCache(long refreshTimeMillis);  AsyncLoadingCache(long refreshTimeMillis, long deadlineTimeMillis);  AsyncLoadingCache(long refreshTimeMillis, long deadlineTimeMillis, long maxSize); @SuppressWarnings("squid:S2789") // comparison of null and optional used to differentiate absence of key and presence of null @Nonnull CompletableFuture<V> orElseGet(@Nonnull K key, @Nonnull Supplier<CompletableFuture<V>> supplier); long getRefreshTimeSeconds(); long getMaxSize(); void clear(); @Override String toString(); }
AsyncLoadingCache { @SuppressWarnings("squid:S2789") @Nonnull public CompletableFuture<V> orElseGet(@Nonnull K key, @Nonnull Supplier<CompletableFuture<V>> supplier) { try { Optional<V> cachedValue = cache.getIfPresent(key); if (cachedValue == null) { return MoreAsyncUtil.getWithDeadline(deadlineTimeMillis, supplier).thenApply(value -> { final Optional<V> existingValue = cache.asMap().putIfAbsent(key, Optional.ofNullable(value)); return existingValue == null ? value : existingValue.orElse(null); }); } else { return CompletableFuture.completedFuture(cachedValue.orElse(null)); } } catch (Exception e) { throw new RecordCoreException("failed getting value", e).addLogInfo("cacheKey", key); } } AsyncLoadingCache(long refreshTimeMillis);  AsyncLoadingCache(long refreshTimeMillis, long deadlineTimeMillis);  AsyncLoadingCache(long refreshTimeMillis, long deadlineTimeMillis, long maxSize); @SuppressWarnings("squid:S2789") // comparison of null and optional used to differentiate absence of key and presence of null @Nonnull CompletableFuture<V> orElseGet(@Nonnull K key, @Nonnull Supplier<CompletableFuture<V>> supplier); long getRefreshTimeSeconds(); long getMaxSize(); void clear(); @Override String toString(); static final long DEFAULT_DEADLINE_TIME_MILLIS; static final long UNLIMITED; }