Don't use forbidden API in FailableCache
This commit is contained in:
parent
57c5efacf6
commit
bd025080c4
|
@ -16,12 +16,7 @@
|
|||
|
||||
package org.elasticsearch.common.inject.internal;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import org.elasticsearch.common.SuppressForbidden;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Lazily creates (and caches) values for keys. If creating the value fails (with errors), an
|
||||
|
@ -29,39 +24,40 @@ import java.util.concurrent.ExecutionException;
|
|||
*
|
||||
* @author jessewilson@google.com (Jesse Wilson)
|
||||
*/
|
||||
// TODO remove this suppression once we get rid of the CacheBuilder and friends
|
||||
@SuppressForbidden(reason = "this uses Function in it's method declaration somewhere")
|
||||
public abstract class FailableCache<K, V> {
|
||||
|
||||
private final LoadingCache<K, Object> delegate = CacheBuilder.newBuilder().build(new CacheLoader<K, Object>() {
|
||||
@Override
|
||||
public Object load(K key) throws Exception {
|
||||
Errors errors = new Errors();
|
||||
V result = null;
|
||||
try {
|
||||
result = FailableCache.this.create(key, errors);
|
||||
} catch (ErrorsException e) {
|
||||
errors.merge(e.getErrors());
|
||||
}
|
||||
return errors.hasErrors() ? errors : result;
|
||||
}
|
||||
});
|
||||
private final ConcurrentHashMap<K, Object> cache = new ConcurrentHashMap<>();
|
||||
|
||||
protected abstract V create(K key, Errors errors) throws ErrorsException;
|
||||
|
||||
public V get(K key, Errors errors) throws ErrorsException {
|
||||
try {
|
||||
Object resultOrError = delegate.get(key);
|
||||
if (resultOrError instanceof Errors) {
|
||||
errors.merge((Errors) resultOrError);
|
||||
throw errors.toException();
|
||||
} else {
|
||||
@SuppressWarnings("unchecked") // create returned a non-error result, so this is safe
|
||||
V result = (V) resultOrError;
|
||||
return result;
|
||||
Object resultOrError = cache.get(key);
|
||||
if (resultOrError == null) {
|
||||
synchronized (this) {
|
||||
resultOrError = load(key);
|
||||
// we can't use cache.computeIfAbsent since this might be recursively call this API
|
||||
cache.putIfAbsent(key, resultOrError);
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (resultOrError instanceof Errors) {
|
||||
errors.merge((Errors) resultOrError);
|
||||
throw errors.toException();
|
||||
} else {
|
||||
@SuppressWarnings("unchecked") // create returned a non-error result, so this is safe
|
||||
V result = (V) resultOrError;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Object load(K key) {
|
||||
Errors errors = new Errors();
|
||||
V result = null;
|
||||
try {
|
||||
result = create(key, errors);
|
||||
} catch (ErrorsException e) {
|
||||
errors.merge(e.getErrors());
|
||||
}
|
||||
return errors.hasErrors() ? errors : result;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue