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;
|
package org.elasticsearch.common.inject.internal;
|
||||||
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import com.google.common.cache.CacheLoader;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
|
||||||
import org.elasticsearch.common.SuppressForbidden;
|
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lazily creates (and caches) values for keys. If creating the value fails (with errors), an
|
* 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)
|
* @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> {
|
public abstract class FailableCache<K, V> {
|
||||||
|
|
||||||
private final LoadingCache<K, Object> delegate = CacheBuilder.newBuilder().build(new CacheLoader<K, Object>() {
|
private final ConcurrentHashMap<K, Object> cache = new ConcurrentHashMap<>();
|
||||||
@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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
protected abstract V create(K key, Errors errors) throws ErrorsException;
|
protected abstract V create(K key, Errors errors) throws ErrorsException;
|
||||||
|
|
||||||
public V get(K key, Errors errors) throws ErrorsException {
|
public V get(K key, Errors errors) throws ErrorsException {
|
||||||
try {
|
Object resultOrError = cache.get(key);
|
||||||
Object resultOrError = delegate.get(key);
|
if (resultOrError == null) {
|
||||||
if (resultOrError instanceof Errors) {
|
synchronized (this) {
|
||||||
errors.merge((Errors) resultOrError);
|
resultOrError = load(key);
|
||||||
throw errors.toException();
|
// we can't use cache.computeIfAbsent since this might be recursively call this API
|
||||||
} else {
|
cache.putIfAbsent(key, resultOrError);
|
||||||
@SuppressWarnings("unchecked") // create returned a non-error result, so this is safe
|
|
||||||
V result = (V) resultOrError;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
} 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