aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorRoman / Linnea Gräf <roman.graef@gmail.com>2023-02-15 18:50:56 +0100
committerGitHub <noreply@github.com>2023-02-15 18:50:56 +0100
commitd3ca199f904cd72e419c6320eda261f023c71937 (patch)
tree32ea0eb2ceac0e1cb24ab09b21f5e5581f809a39 /src/main/java
parente0ab2af457daf50b838248afbc4110c97a0c8b4a (diff)
downloadNotEnoughUpdates-d3ca199f904cd72e419c6320eda261f023c71937.tar.gz
NotEnoughUpdates-d3ca199f904cd72e419c6320eda261f023c71937.tar.bz2
NotEnoughUpdates-d3ca199f904cd72e419c6320eda261f023c71937.zip
ApiUtil: Add cache with per request timeout and per class histogram (#592)
* ApiUtil: Add cache with per request timeout and per class histogram * MinionHelper: Only load minion helper data when needed * Api: Make api response processing more async. * Lower cache for /pv to 30 seconds and rename cacheDuration to max age * Disk cache for the API
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java14
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java7
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java5
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java38
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java37
9 files changed, 73 insertions, 56 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
index 5ec3724a..ac60ffd9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
@@ -292,7 +292,7 @@ public class APIManager {
.newMoulberryRequest("lowestbin.json.gz")
.gunzip()
.requestJson()
- .thenAccept(jsonObject -> {
+ .thenAcceptAsync(jsonObject -> {
if (lowestBins == null) {
lowestBins = new JsonObject();
}
@@ -465,12 +465,12 @@ public class APIManager {
};
manager.apiUtils.newMoulberryRequest("auctionLast.json.gz")
- .gunzip().requestJson().thenAccept(process);
+ .gunzip().requestJson().thenAcceptAsync(process);
manager.apiUtils
.newMoulberryRequest("auction.json.gz")
.gunzip().requestJson()
- .thenAccept(jsonObject -> {
+ .thenAcceptAsync(jsonObject -> {
if (jsonObject.get("success").getAsBoolean()) {
long apiUpdate = (long) jsonObject.get("time").getAsFloat();
if (lastApiUpdate == apiUpdate) {
@@ -683,7 +683,7 @@ public class APIManager {
manager.apiUtils
.newAnonymousHypixelApiRequest("skyblock/auctions")
.requestJson()
- .thenAccept(jsonObject -> {
+ .thenAcceptAsync(jsonObject -> {
if (jsonObject == null) return;
if (jsonObject.get("success").getAsBoolean()) {
@@ -733,7 +733,7 @@ public class APIManager {
manager.apiUtils
.newAnonymousHypixelApiRequest("skyblock/bazaar")
.requestJson()
- .thenAccept(jsonObject -> {
+ .thenAcceptAsync(jsonObject -> {
if (!jsonObject.get("success").getAsBoolean()) return;
craftCost.clear();
@@ -789,7 +789,7 @@ public class APIManager {
public void updateAvgPrices() {
manager.apiUtils
.newMoulberryRequest("auction_averages/3day.json.gz")
- .gunzip().requestJson().thenAccept((jsonObject) -> {
+ .gunzip().requestJson().thenAcceptAsync((jsonObject) -> {
craftCost.clear();
auctionPricesJson = jsonObject;
lastAuctionAvgUpdate = System.currentTimeMillis();
@@ -797,7 +797,7 @@ public class APIManager {
manager.apiUtils
.newMoulberryRequest("auction_averages_lbin/1day.json.gz")
.gunzip().requestJson()
- .thenAccept((jsonObject) -> {
+ .thenAcceptAsync((jsonObject) -> {
auctionPricesAvgLowestBinJson = jsonObject;
});
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java
index 35474ff3..8dda864a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java
@@ -33,11 +33,13 @@ import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.Locati
import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.SpecialBlockZone;
import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph;
import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager;
+import io.github.moulberry.notenoughupdates.util.ApiCache;
import io.github.moulberry.notenoughupdates.util.PronounDB;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import io.github.moulberry.notenoughupdates.util.TabListUtils;
import io.github.moulberry.notenoughupdates.util.Utils;
import io.github.moulberry.notenoughupdates.util.hypixelapi.ProfileCollectionInfo;
+import lombok.var;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.command.CommandException;
@@ -126,6 +128,24 @@ public class DevTestCommand extends ClientCommandBase {
Utils.addChatMessage(EnumChatFormatting.RED + DEV_FAIL_STRINGS[devFailIndex++]);
return;
}
+ if (args.length == 1 && args[0].equalsIgnoreCase("dumpapihistogram")) {
+ synchronized (ApiCache.INSTANCE) {
+ Utils.addChatMessage("§e[NEU] API Request Histogram");
+ Utils.addChatMessage("§e[NEU] §bClass Name§e: §aCached§e/§cNonCached§e/§dTotal");
+ ApiCache.INSTANCE.getHistogramTotalRequests().forEach((className, totalRequests) -> {
+ var nonCachedRequests = ApiCache.INSTANCE.getHistogramNonCachedRequests().getOrDefault(className, 0);
+ var cachedRequests = totalRequests - nonCachedRequests;
+ Utils.addChatMessage(
+ String.format(
+ "§e[NEU] §b%s §a%d§e/§c%d§e/§d%d",
+ className,
+ cachedRequests,
+ nonCachedRequests,
+ totalRequests
+ ));
+ });
+ }
+ }
if (args.length == 1 && args[0].equalsIgnoreCase("testprofile")) {
NotEnoughUpdates.INSTANCE.manager.apiUtils.newHypixelApiRequest("skyblock/profiles")
.queryArgument(
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java
index 5a4f1400..cf0d0c56 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java
@@ -88,7 +88,7 @@ public class PronounsCommand extends ClientCommandBase {
"§e[NEU] Pronouns for §b" + user + " §eon §b" + platform + "§e:"), id);
betterPronounChoice.render().forEach(it -> nc.printChatMessage(new ChatComponentText("§e[NEU] §a" + it)));
return null;
- }, MinecraftExecutor.INSTANCE);
+ }, MinecraftExecutor.OnThread);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
index 4a7c1939..984a7931 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
@@ -150,7 +150,7 @@ public class CapeManager {
NotEnoughUpdates.INSTANCE.manager.apiUtils
.newMoulberryRequest("activecapes.json")
.requestJson()
- .thenAccept(jsonObject -> {
+ .thenAcceptAsync(jsonObject -> {
if (jsonObject.get("success").getAsBoolean()) {
lastJsonSync = jsonObject;
@@ -171,7 +171,7 @@ public class CapeManager {
NotEnoughUpdates.INSTANCE.manager.apiUtils
.newMoulberryRequest("permscapes.json")
.requestJson()
- .thenAccept(jsonObject -> {
+ .thenAcceptAsync(jsonObject -> {
if (!jsonObject.get("success").getAsBoolean()) return;
permSyncTries = 0;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java
index aaa398f4..ecf02236 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java
@@ -47,7 +47,6 @@ import java.util.Map;
public class MinionHelperApiLoader {
private final MinionHelperManager manager;
private boolean dirty = true;
- private int ticks = 0;
private boolean collectionApiEnabled = true;
private boolean ignoreWorldSwitches = false;
private boolean readyToUse = false;
@@ -72,11 +71,7 @@ public class MinionHelperApiLoader {
if (Minecraft.getMinecraft().thePlayer == null) return;
if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return;
if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) return;
- ticks++;
-
- if (ticks % 20 != 0) return;
-
- if (dirty) {
+ if (dirty && "Crafted Minions".equals(Utils.getOpenChestName())) {
load();
} else {
if (System.currentTimeMillis() > lastLoaded + 60_000 * 3) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java b/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java
index 50f459c0..90ef93bb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java
@@ -31,6 +31,7 @@ public enum NEUDebugFlag {
WISHING("Wishing Compass Solver"),
MAP("Dungeon Map Player Information"),
SEARCH("SearchString Matches"),
+ API_CACHE("Api Cache"),
;
private final String description;
@@ -43,6 +44,10 @@ public enum NEUDebugFlag {
return description;
}
+ public void log(String message) {
+ NEUDebugLogger.log(this, message);
+ }
+
public boolean isSet() {
return NEUDebugLogger.isFlagEnabled(this);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
index 17a14d1f..6f8427ae 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
@@ -42,6 +42,7 @@ import net.minecraft.util.EnumChatFormatting;
import javax.annotation.Nullable;
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
@@ -537,6 +538,7 @@ public class ProfileViewer {
manager.apiUtils
.newHypixelApiRequest("player")
.queryArgument("name", nameF)
+ .maxCacheAge(Duration.ofSeconds(30))
.requestJson()
.thenAccept(jsonObject -> {
if (
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
index 45522329..28298fe0 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
@@ -48,18 +48,26 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.GZIPInputStream;
public class ApiUtil {
private static final Gson gson = new Gson();
+
+ private static final Comparator<NameValuePair> nameValuePairComparator = Comparator
+ .comparing(NameValuePair::getName)
+ .thenComparing(NameValuePair::getValue);
+
private static final ExecutorService executorService = Executors.newFixedThreadPool(3);
private static String getUserAgent() {
if (NotEnoughUpdates.INSTANCE.config.hidden.customUserAgent != null) {
@@ -110,6 +118,7 @@ public class ApiUtil {
private final List<NameValuePair> queryArguments = new ArrayList<>();
private String baseUrl = null;
private boolean shouldGunzip = false;
+ private Duration maxCacheAge = Duration.ofSeconds(500);
private String method = "GET";
private String postData = null;
private String postContentType = null;
@@ -119,6 +128,15 @@ public class ApiUtil {
return this;
}
+ /**
+ * Specify a cache timeout of {@code null} to signify an uncacheable request.
+ * Non {@code GET} requests are always uncacheable.
+ */
+ public Request maxCacheAge(Duration maxCacheAge) {
+ this.maxCacheAge = maxCacheAge;
+ return this;
+ }
+
public Request url(String baseUrl) {
this.baseUrl = baseUrl;
return this;
@@ -160,7 +178,17 @@ public class ApiUtil {
return fut;
}
- public CompletableFuture<String> requestString() {
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ private ApiCache.CacheKey getCacheKey() {
+ if (!"GET".equals(method)) return null;
+ queryArguments.sort(nameValuePairComparator);
+ return new ApiCache.CacheKey(baseUrl, queryArguments, shouldGunzip);
+ }
+
+ private CompletableFuture<String> requestString0() {
return buildUrl().thenApplyAsync(url -> {
try {
InputStream inputStream = null;
@@ -183,7 +211,7 @@ public class ApiUtil {
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
try {
- os.write(this.postData.getBytes("utf-8"));
+ os.write(this.postData.getBytes(StandardCharsets.UTF_8));
} finally {
os.close();
}
@@ -221,12 +249,16 @@ public class ApiUtil {
});
}
+ public CompletableFuture<String> requestString() {
+ return ApiCache.INSTANCE.cacheRequest(this, getCacheKey(), this::requestString0, maxCacheAge);
+ }
+
public CompletableFuture<JsonObject> requestJson() {
return requestJson(JsonObject.class);
}
public <T> CompletableFuture<T> requestJson(Class<? extends T> clazz) {
- return requestString().thenApply(str -> gson.fromJson(str, clazz));
+ return requestString().thenApplyAsync(str -> gson.fromJson(str, clazz));
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java b/src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java
deleted file mode 100644
index bf973b76..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2022 NotEnoughUpdates contributors
- *
- * This file is part of NotEnoughUpdates.
- *
- * NotEnoughUpdates is free software: you can redistribute it
- * and/or modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * NotEnoughUpdates is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package io.github.moulberry.notenoughupdates.util;
-
-import net.minecraft.client.Minecraft;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.concurrent.Executor;
-
-public class MinecraftExecutor implements Executor {
-
- public static MinecraftExecutor INSTANCE = new MinecraftExecutor();
-
- private MinecraftExecutor() {}
-
- @Override
- public void execute(@NotNull Runnable runnable) {
- Minecraft.getMinecraft().addScheduledTask(runnable);
- }
-}