@Test public void cacheNulls() { AsyncLoadingCache<String, String> cache = new AsyncLoadingCache<>(100); final AtomicInteger counter = new AtomicInteger(); CompletableFuture<Void> signal = new CompletableFuture<>(); final Supplier<CompletableFuture<String>> supplier = () -> { counter.incrementAndGet(); return signal.thenApply(ignored -> null); }; CompletableFuture<String> future = cache.orElseGet("key", supplier); assertEquals(1, counter.get()); signal.complete(null); String value = future.join(); assertNull(value); CompletableFuture<String> cachedFuture = cache.orElseGet("key", supplier); assertEquals(1, counter.get()); value = cachedFuture.join(); assertNull(value); }
@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; }