-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AsyncCacheLoader for asynchronous caches (fixes #53)
Creating an AsyncLoadingCache previously required passing a CacheLoader to Caffine.buildAsync(), optionally as a lambda. This is convenient when the computations are written in a synchronous fashion and the cache provides the asynchronous wrapping. That API was clunky when the computation is defined asynchronously, such as when bubbling up a future from another library. In that case the asyncLoad default method had to be overriden in addition to load (which may never be called). It offered all the power needed but in a combersome fashion. AsyncCacheLoader resolves this API flaw by providing the asynchronous computations that a loader can make (asyncLoad, asyncLoadAll, and asyncReload). It can be used as a lambda for buildAsync, e.g. (key, executor) -> future. Backwards compatibility is retained by having the CacheLoader extend AsyncCacheLoader. The asyncLoad and asyncLoadAll were already defined as defaults, so only asyncReload was introduced. This approach is nice by providing symmetry, low integration effort, and minimal impact to the API.
- Loading branch information
Showing
22 changed files
with
326 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
caffeine/src/main/java/com/github/benmanes/caffeine/cache/AsyncCacheLoader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* Copyright 2016 Ben Manes. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.github.benmanes.caffeine.cache; | ||
|
||
import java.util.Map; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.Executor; | ||
|
||
import javax.annotation.Nonnull; | ||
import javax.annotation.concurrent.ThreadSafe; | ||
|
||
/** | ||
* Computes or retrieves values asynchronously, based on a key, for use in populating a | ||
* {@link AsyncLoadingCache}. | ||
* <p> | ||
* Most implementations will only need to implement {@link #asyncLoad}. Other methods may be | ||
* overridden as desired. | ||
* <p> | ||
* Usage example: | ||
* <pre>{@code | ||
* AsyncCacheLoader<Key, Graph> loader = (key, executor) -> | ||
* createExpensiveGraphAsync(key, executor); | ||
* AsyncLoadingCache<Key, Graph> cache = Caffeine.newBuilder().build(loader); | ||
* }</pre> | ||
* | ||
* @author [email protected] (Ben Manes) | ||
*/ | ||
@ThreadSafe | ||
@FunctionalInterface | ||
public interface AsyncCacheLoader<K, V> { | ||
|
||
/** | ||
* Asynchronously computes or retrieves the value corresponding to {@code key}. | ||
* | ||
* @param key the non-null key whose value should be loaded | ||
* @param executor the executor with which the entry is asynchronously loaded | ||
* @return the future value associated with {@code key} | ||
*/ | ||
@Nonnull | ||
CompletableFuture<V> asyncLoad(@Nonnull K key, @Nonnull Executor executor); | ||
|
||
/** | ||
* Asynchronously computes or retrieves the values corresponding to {@code keys}. This method is | ||
* called by {@link AsyncLoadingCache#getAll}. | ||
* <p> | ||
* If the returned map doesn't contain all requested {@code keys} then the entries it does contain | ||
* will be cached and {@code getAll} will return the partial results. If the returned map contains | ||
* extra keys not present in {@code keys} then all returned entries will be cached, but only the | ||
* entries for {@code keys} will be returned from {@code getAll}. | ||
* <p> | ||
* This method should be overridden when bulk retrieval is significantly more efficient than many | ||
* individual lookups. Note that {@link AsyncLoadingCache#getAll} will defer to individual calls | ||
* to {@link AsyncLoadingCache#get} if this method is not overridden. | ||
* | ||
* @param keys the unique, non-null keys whose values should be loaded | ||
* @param executor the executor with which the entries are asynchronously loaded | ||
* @return a future containing the map from each key in {@code keys} to the value associated with | ||
* that key; <b>may not contain null values</b> | ||
*/ | ||
@Nonnull | ||
default CompletableFuture<Map<K, V>> asyncLoadAll( | ||
@Nonnull Iterable<? extends K> keys, @Nonnull Executor executor) { | ||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
/** | ||
* Asynchronously computes or retrieves a replacement value corresponding to an already-cached | ||
* {@code key}. If the replacement value is not found then the mapping will be removed if | ||
* {@code null} is computed. This method is called when an existing cache entry is refreshed by | ||
* {@link Caffeine#refreshAfterWrite}, or through a call to {@link LoadingCache#refresh}. | ||
* <p> | ||
* <b>Note:</b> <i>all exceptions thrown by this method will be logged and then swallowed</i>. | ||
* | ||
* @param key the non-null key whose value should be loaded | ||
* @param oldValue the non-null old value corresponding to {@code key} | ||
* @param executor the executor with which the entry is asynchronously loaded | ||
* @return a future containing the new value associated with {@code key}, or containing | ||
* {@code null} if the mapping is to be removed | ||
*/ | ||
@Nonnull | ||
default CompletableFuture<V> asyncReload( | ||
@Nonnull K key, @Nonnull V oldValue, @Nonnull Executor executor) { | ||
return asyncLoad(key, executor); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.