private Document getXmlResource(int aid) throws Exception {
synchronized (BANNED) {
CachedResource<Integer, Document> resource = getResourceCache().xml(aid, this::getResource).fetch(withPermit(fetchIfModified(), r -> {
if (BANNED.get()) {
throw new IllegalStateException("AniDB has already banned your IP. Please stop hitting AniDB for at least 24 hours.");
}
if (HARD_LIMIT.availablePermits() == 0) {
log.warning("AniDB HTTP API daily limit has been exceeded. Processing will continue in 24 hours...");
Cache.DISK_STORE.flush();
TimeUnit.HOURS.sleep(24);
}
debug.finest(message("AniDB daily limit", HARD_LIMIT));
HARD_LIMIT.acquirePermit();
debug.finest(message("AniDB minutely limit", SOFT_LIMIT));
SOFT_LIMIT.acquirePermit();
})).expire(Cache.ONE_WEEK);
// disable weekly expiration
if ((BANNED.get() || HARD_LIMIT.availablePermits() < 100) && resource.available()) {
log.config(message("AniDB cache expiration temporarily disabled due to heavy usage", aid, HARD_LIMIT));
resource.expire(Cache.NEVER);
}
// retrieve resource
Document dom = resource.get();
// check for errors (e.g. <error>Banned</error>)
String error = selectString("/error", dom);
if (error != null && !error.isEmpty()) {
// client error (cache expected response)
if ("anime not found".equalsIgnoreCase(error)) {
throw new LookupException(error, aid);
}
// server errors (do not cache unexpected response)
resource.invalidate();
if ("banned".equalsIgnoreCase(error)) {
BANNED.set(true);
throw new InvalidResponseException("AniDB has banned your IP due to excessive usage. Please try again in 24 hours or later.");
}
// unknown error
throw new InvalidResponseException(error);
}
return dom;
}
}
Comments