Object readResolve() { Caffeine<Object, Object> builder = recreateCaffeine(); if (async) { if (loader == null) { return builder.buildAsync(); } @SuppressWarnings("unchecked") AsyncCacheLoader<K, V> cacheLoader = (AsyncCacheLoader<K, V>) loader; return builder.buildAsync(cacheLoader); } if (loader == null) { return builder.build(); } @SuppressWarnings("unchecked") CacheLoader<K, V> cacheLoader = (CacheLoader<K, V>) loader; return builder.build(cacheLoader); } }
/** * Builds a cache, which either returns a {@link CompletableFuture} already loaded or currently * computing the value for a given key, or atomically computes the value asynchronously through a * supplied mapping function or the supplied {@code CacheLoader}. If the asynchronous computation * fails or computes a {@code null} value then the entry will be automatically removed. Note that * multiple threads can concurrently load values for distinct keys. * <p> * This method does not alter the state of this {@code Caffeine} instance, so it can be invoked * again to create multiple independent caches. * <p> * This construction cannot be used with {@link #weakValues()}, {@link #softValues()}, or * {@link #writer(CacheWriter)}. * * @param loader the cache loader used to obtain new values * @param <K1> the key type of the loader * @param <V1> the value type of the loader * @return a cache having the requested features */ @NonNull public <K1 extends K, V1 extends V> AsyncLoadingCache<K1, V1> buildAsync( @NonNull CacheLoader<? super K1, V1> loader) { return buildAsync((AsyncCacheLoader<? super K1, V1>) loader); }
@Test public void async_nullLoader() { try { Caffeine.newBuilder().buildAsync((CacheLoader<Object, Object>) null); Assert.fail(); } catch (NullPointerException expected) {} try { Caffeine.newBuilder().buildAsync((AsyncCacheLoader<Object, Object>) null); Assert.fail(); } catch (NullPointerException expected) {} }
@Test public void async_asyncLoader() { Caffeine.newBuilder().buildAsync(loader::asyncLoad); }
@Test public void unconfigured() { assertThat(Caffeine.newBuilder().build(), is(not(nullValue()))); assertThat(Caffeine.newBuilder().build(loader), is(not(nullValue()))); assertThat(Caffeine.newBuilder().buildAsync(), is(not(nullValue()))); assertThat(Caffeine.newBuilder().buildAsync(loader), is(not(nullValue()))); assertThat(Caffeine.newBuilder().toString(), is(Caffeine.newBuilder().toString())); }
@Test(expectedExceptions = IllegalStateException.class) public void async_weakValues() { Caffeine.newBuilder().weakValues().buildAsync(loader); }
@Test(expectedExceptions = IllegalStateException.class) public void async_writer() { Caffeine.newBuilder().writer(writer).buildAsync(loader); }
@Test(expectedExceptions = IllegalStateException.class) public void async_softValues() { Caffeine.newBuilder().softValues().buildAsync(loader); }
@DataProvider(name = "params") public Object[][] providesCache() { ConcurrentMap<String, String> source = new ConcurrentHashMap<>(); ConcurrentMap<String, Date> lastLoad = new ConcurrentHashMap<>(); AsyncLoadingCache<String, String> cache = Caffeine.newBuilder() .expireAfterWrite(TTL, TimeUnit.MILLISECONDS) .executor(executor) .buildAsync(new Loader(source, lastLoad)); return new Object[][] {{ cache, source, lastLoad }}; }
public <K, V> AsyncLoadingCache<K, V> buildAsync(AsyncCacheLoader<K, V> loader) { checkState(isCaffeine() && isAsync()); AsyncLoadingCache<K, V> cache = caffeine.buildAsync(loader); this.cache = cache.synchronous(); return cache; }
public <K, V> AsyncLoadingCache<K, V> buildAsync(CacheLoader<K, V> loader) { checkState(isCaffeine() && isAsync()); AsyncLoadingCache<K, V> cache = caffeine.buildAsync(loader); this.cache = cache.synchronous(); return cache; }
@Test public void configured() { Caffeine<Object, Object> configured = Caffeine.newBuilder() .initialCapacity(1).weakKeys() .expireAfterAccess(1, TimeUnit.SECONDS).expireAfterWrite(1, TimeUnit.SECONDS) .removalListener((k, v, c) -> {}).recordStats(); assertThat(configured.build(), is(not(nullValue()))); assertThat(configured.buildAsync(), is(not(nullValue()))); assertThat(configured.build(loader), is(not(nullValue()))); assertThat(configured.buildAsync(loader), is(not(nullValue()))); assertThat(configured.refreshAfterWrite(1, TimeUnit.SECONDS).toString(), is(not(Caffeine.newBuilder().toString()))); assertThat(Caffeine.newBuilder().maximumSize(1).toString(), is(not(Caffeine.newBuilder().maximumWeight(1).toString()))); }
public <K, V> LoadingCache<K, V> build(CacheLoader<K, V> loader) { LoadingCache<K, V> cache; if (isCaffeine()) { cache = isAsync() ? caffeine.buildAsync(loader).synchronous() : caffeine.build(loader); } else { cache = new GuavaLoadingCache<>(guava.build( com.google.common.cache.CacheLoader.asyncReloading( new SingleLoader<>(loader), executor)), ticker, isRecordingStats()); } this.cache = cache; return cache; }
private static void addUnboundedTests(TestSuite suite) throws Exception { suite.addTest(MapTestFactory.suite("UnboundedCache", () -> { Cache<String, String> cache = Caffeine.newBuilder().build(); return cache.asMap(); })); suite.addTest(MapTestFactory.suite("UnboundedAsyncCache", () -> { AsyncLoadingCache<String, String> cache = Caffeine.newBuilder().buildAsync(key -> null); return cache.synchronous().asMap(); })); }
private static void addBoundedTests(TestSuite suite) throws Exception { suite.addTest(MapTestFactory.suite("BoundedCache", () -> { Cache<String, String> cache = Caffeine.newBuilder().maximumSize(Long.MAX_VALUE).build(); return cache.asMap(); })); suite.addTest(MapTestFactory.suite("BoundedAsyncCache", () -> { AsyncLoadingCache<String, String> cache = Caffeine.newBuilder() .maximumSize(Long.MAX_VALUE) .buildAsync(key -> null); return cache.synchronous().asMap(); })); }
/** * Builds a cache, which either returns a {@link CompletableFuture} already loaded or currently * computing the value for a given key, or atomically computes the value asynchronously through a * supplied mapping function or the supplied {@code CacheLoader}. If the asynchronous computation * fails or computes a {@code null} value then the entry will be automatically removed. Note that * multiple threads can concurrently load values for distinct keys. * <p> * This method does not alter the state of this {@code Caffeine} instance, so it can be invoked * again to create multiple independent caches. * <p> * This construction cannot be used with {@link #weakValues()}, {@link #softValues()}, or * {@link #writer}. * * @param loader the cache loader used to obtain new values * @param <K1> the key type of the loader * @param <V1> the value type of the loader * @return a cache having the requested features */ @Nonnull public <K1 extends K, V1 extends V> AsyncLoadingCache<K1, V1> buildAsync( @Nonnull CacheLoader<? super K1, V1> loader) { return buildAsync((AsyncCacheLoader<? super K1, V1>) loader); }
Object readResolve() { Caffeine<Object, Object> builder = recreateCaffeine(); if (loader == null) { return builder.build(); } else if (async) { @SuppressWarnings("unchecked") AsyncCacheLoader<K, V> cacheLoader = (AsyncCacheLoader<K, V>) loader; return builder.buildAsync(cacheLoader); } else { @SuppressWarnings("unchecked") CacheLoader<K, V> cacheLoader = (CacheLoader<K, V>) loader; return builder.build(cacheLoader); } } }
context.asyncCache = builder.buildAsync(); } else { context.asyncCache = builder.buildAsync( context.isAsyncLoading ? context.loader.async() : context.loader);
CalculatedSubject(SubjectDataBaker baker, Map.Entry<String, String> identifier, SubjectType type) { this.baker = Preconditions.checkNotNull(baker, "baker"); this.identifier = Preconditions.checkNotNull(identifier, "identifier"); this.type = Preconditions.checkNotNull(type, "type"); this.data = Caffeine.newBuilder() .maximumSize(32) .expireAfterAccess(30, TimeUnit.MINUTES) .buildAsync(((key, executor) -> this.baker.bake(CalculatedSubject.this, key))); }
public void update(DataStore newDataStore) { this.dataStore = newDataStore; AsyncLoadingCache<String, ImmutableSubjectData> oldCache = this.cache.getAndSet(Caffeine.newBuilder() .maximumSize(512) .buildAsync(((key, executor) -> dataStore.getData(type, key, clearListener(key))))); if (oldCache != null) { oldCache.synchronous().asMap().forEach((k, v) -> { getData(k, null).thenAccept(data -> listeners.call(k, data)); // TODO: Not ignore this somehow? Add a listener in to the backend? }); } }