private <T extends Document> T readDocumentCached(final Collection<T> collection, final String id, int maxCacheAge) {
if (collection != Collection.NODES) {
return readDocumentUncached(collection, id);
} else {
CacheValue cacheKey = new StringValue(id);
NodeDocument doc;
if (maxCacheAge > 0) {
// first try without lock
doc = nodesCache.getIfPresent(cacheKey);
if (doc != null) {
if (maxCacheAge == Integer.MAX_VALUE || System.currentTimeMillis() - doc.getLastCheckTime() < maxCacheAge) {
return castAsT(unwrap(doc));
}
}
}
try {
Lock lock = getAndLock(id);
try {
if (maxCacheAge == 0) {
invalidateCache(collection, id);
}
while (true) {
doc = nodesCache.get(cacheKey, new Callable<NodeDocument>() {
@Override
public NodeDocument call() throws Exception {
NodeDocument doc = (NodeDocument) readDocumentUncached(collection, id);
if (doc != null) {
doc.seal();
}
return wrap(doc);
}
});
if (maxCacheAge == 0 || maxCacheAge == Integer.MAX_VALUE) {
break;
}
if (System.currentTimeMillis() - doc.getCreated() < maxCacheAge) {
break;
}
// too old: invalidate, try again
invalidateCache(collection, id);
}