in evcache-core/src/main/java/com/netflix/evcache/EVCacheImpl.java [1795:1885]
private <T> Future<T> getGetFuture(final EVCacheClient client, final String key, final Transcoder<T> tc, final boolean throwExc) throws EVCacheException {
final EVCacheKey evcKey = getEVCacheKey(key);
final EVCacheEvent event = createEVCacheEvent(Collections.singletonList(client), Call.ASYNC_GET);
if (event != null) {
event.setEVCacheKeys(Arrays.asList(evcKey));
try {
if (shouldThrottle(event)) {
incrementFastFail(EVCacheMetricsFactory.THROTTLED, Call.ASYNC_GET);
if (throwExc) throw new EVCacheException("Request Throttled for app " + _appName + " & key " + key);
return null;
}
} catch(EVCacheException ex) {
if(throwExc) throw ex;
incrementFastFail(EVCacheMetricsFactory.THROTTLED, Call.ASYNC_GET);
return null;
}
startEvent(event);
}
String status = EVCacheMetricsFactory.SUCCESS;
final Future<T> r;
final long start = EVCacheMetricsFactory.getInstance().getRegistry().clock().wallTime();
try {
String hashKey = evcKey.getHashKey(client.isDuetClient(), client.getHashingAlgorithm(), client.shouldEncodeHashKey(), client.getMaxDigestBytes(), client.getMaxHashLength(), client.getBaseEncoder());
String canonicalKey = evcKey.getCanonicalKey(client.isDuetClient());
if(hashKey != null) {
final Future<Object> objFuture = client.asyncGet(hashKey, evcacheValueTranscoder, throwExc, false);
r = new Future<T> () {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return objFuture.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return objFuture.isCancelled();
}
@Override
public boolean isDone() {
return objFuture.isDone();
}
@Override
public T get() throws InterruptedException, ExecutionException {
return getFromObj(objFuture.get());
}
private T getFromObj(Object obj) {
if(obj != null && obj instanceof EVCacheValue) {
final EVCacheValue val = (EVCacheValue)obj;
if(!val.getKey().equals(canonicalKey)) {
incrementFailure(EVCacheMetricsFactory.KEY_HASH_COLLISION, Call.ASYNC_GET.name(), EVCacheMetricsFactory.READ);
return null;
}
final CachedData cd = new CachedData(val.getFlags(), val.getValue(), CachedData.MAX_SIZE);
final Transcoder<T> transcoder = (tc == null) ? ((_transcoder == null) ? (Transcoder<T>) client.getTranscoder() : (Transcoder<T>) _transcoder) : tc;
return transcoder.decode(cd);
} else {
return null;
}
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return getFromObj(objFuture.get(timeout, unit));
}
};
} else {
final Transcoder<T> transcoder = (tc == null) ? ((_transcoder == null) ? (Transcoder<T>) client.getTranscoder() : (Transcoder<T>) _transcoder) : tc;
r = client.asyncGet(canonicalKey, transcoder, throwExc, false);
}
if (event != null) endEvent(event);
} catch (Exception ex) {
status = EVCacheMetricsFactory.ERROR;
if (log.isDebugEnabled() && shouldLog()) log.debug( "Exception while getting data for keys Asynchronously APP " + _appName + ", key : " + key, ex);
if (event != null) {
event.setStatus(status);
eventError(event, ex);
}
if (!throwExc) return null;
throw new EVCacheException("Exception getting data for APP " + _appName + ", key : " + key, ex);
} finally {
final long duration = EVCacheMetricsFactory.getInstance().getRegistry().clock().wallTime()- start;
getTimer(Call.ASYNC_GET.name(), EVCacheMetricsFactory.READ, null, status, 1, maxReadDuration.get().intValue(), client.getServerGroup()).record(duration, TimeUnit.MILLISECONDS);
if (log.isDebugEnabled() && shouldLog()) log.debug("Took " + duration + " milliSec to execute AsyncGet the value for APP " + _appName + ", key " + key);
}
return r;
}