From c4012fe697711459499c4b2e86e62b0c7b2cb25f Mon Sep 17 00:00:00 2001 From: TheBusyBiscuit Date: Sat, 16 May 2020 12:04:19 +0200 Subject: [PATCH] [ci skip] Reduced mojang.com connection errors --- CHANGELOG.md | 1 + .../github/ContributionsConnector.java | 21 ++++++-- .../core/services/github/Contributor.java | 24 +++++++++ .../core/services/github/GitHubService.java | 28 +++++++++++ .../core/services/github/GitHubTask.java | 49 ++++++++++++++----- 5 files changed, 107 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d6a143a2..a0a09698c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ * Fixed Organic Food/Fertilizer not being recognized * Fixed #1883 * Fixed #1829 +* Fixed some mojang.com connection errors ## Release Candidate 11 (25 Apr 2020) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java index b599a4f24..5f50d2783 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/ContributionsConnector.java @@ -37,6 +37,8 @@ class ContributionsConnector extends GitHubConnector { private final String role; private final int page; + private boolean finished = false; + ContributionsConnector(GitHubService github, String prefix, int page, String repository, String role) { super(github, repository); @@ -45,8 +47,18 @@ class ContributionsConnector extends GitHubConnector { this.role = role; } + /** + * This returns whether this {@link ContributionsConnector} has finished its task. + * + * @return Whether it is finished + */ + public boolean hasFinished() { + return finished; + } + @Override public void onSuccess(JsonElement element) { + finished = true; if (element.isJsonArray()) { computeContributors(element.getAsJsonArray()); } @@ -55,6 +67,11 @@ class ContributionsConnector extends GitHubConnector { } } + @Override + public void onFailure() { + finished = true; + } + @Override public String getFileName() { return prefix + "_contributors"; @@ -74,9 +91,7 @@ class ContributionsConnector extends GitHubConnector { String profile = object.get("html_url").getAsString(); if (!blacklist.contains(name)) { - Contributor contributor = github.getContributors().computeIfAbsent(name, key -> new Contributor(aliases.getOrDefault(name, name), profile)); - - contributor.setContribution(role, commits); + github.addContributor(aliases.getOrDefault(name, name), profile, role, commits); } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/Contributor.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/Contributor.java index 36f3307a4..ed4dea231 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/Contributor.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/Contributor.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -27,9 +29,11 @@ public class Contributor { private final String githubUsername; private final String minecraftUsername; private final String profileLink; + private final ConcurrentMap contributions = new ConcurrentHashMap<>(); private final ComputedOptional headTexture = ComputedOptional.createNew(); + private Optional uuid = Optional.empty(); private boolean locked = false; public Contributor(String username, String profile) { @@ -96,6 +100,26 @@ public class Contributor { return contributions.getOrDefault(role, 0); } + /** + * This method sets the {@link UUID} for this {@link Contributor}. + * + * @param uuid + * The {@link UUID} for this {@link Contributor} + */ + public void setUniqueId(UUID uuid) { + this.uuid = uuid == null ? Optional.empty() : Optional.of(uuid); + } + + /** + * This returns the {@link UUID} for this {@link Contributor}. + * This {@link UUID} may be loaded from a cache. + * + * @return The {@link UUID} of this {@link Contributor} + */ + public Optional getUniqueId() { + return uuid; + } + /** * Returns this Creator's head texture. * If no texture could be found, or it hasn't been pulled yet, diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java index b8822be33..1938a0c01 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubService.java @@ -1,14 +1,18 @@ package io.github.thebusybiscuit.slimefun4.core.services.github; +import java.io.File; import java.time.LocalDateTime; import java.util.HashSet; +import java.util.Optional; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import io.github.thebusybiscuit.cscorelib2.config.Config; import io.github.thebusybiscuit.slimefun4.core.services.localization.Translators; import io.github.thebusybiscuit.slimefun4.utils.NumberUtils; import me.mrCookieSlime.Slimefun.SlimefunPlugin; @@ -26,6 +30,7 @@ public class GitHubService { private final String repository; private final Set connectors; private final ConcurrentMap contributors; + private final Config uuidCache = new Config("plugins/Slimefun/cache/github/uuids.yml"); private boolean logging = false; @@ -64,9 +69,16 @@ public class GitHubService { private void addContributor(String name, String role) { Contributor contributor = new Contributor(name); contributor.setContribution(role, 0); + contributor.setUniqueId(uuidCache.getUUID(name)); contributors.put(name, contributor); } + protected void addContributor(String name, String profile, String role, int commits) { + Contributor contributor = contributors.computeIfAbsent(name, key -> new Contributor(name, profile)); + contributor.setContribution(role, commits); + contributor.setUniqueId(uuidCache.getUUID(name)); + } + private void loadConnectors(boolean logging) { this.logging = logging; addDefaultContributors(); @@ -179,4 +191,20 @@ public class GitHubService { public LocalDateTime getLastUpdate() { return lastUpdate; } + + /** + * This will store the {@link UUID} of all {@link Contributor Contributors} in memory + * in a {@link File} to save requests the next time we iterate over them. + */ + protected void saveUUIDCache() { + for (Contributor contributor : contributors.values()) { + Optional uuid = contributor.getUniqueId(); + + if (uuid.isPresent()) { + uuidCache.setValue(contributor.getName(), uuid.get()); + } + } + + uuidCache.save(); + } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java index 7aa5bf9db..80434f687 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/core/services/github/GitHubTask.java @@ -26,7 +26,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun; */ class GitHubTask implements Runnable { - private static final int MAX_REQUESTS_PER_MINUTE = 10; + private static final int MAX_REQUESTS_PER_MINUTE = 16; private final GitHubService gitHubService; @@ -54,8 +54,9 @@ class GitHubTask implements Runnable { contributor.setTexture(skins.get(contributor.getMinecraftName())); } else { - contributor.setTexture(grabTexture(skins, contributor.getMinecraftName())); - count++; + contributor.setTexture(grabTexture(skins, contributor)); + + count += contributor.getUniqueId().isPresent() ? 1 : 2; if (count >= MAX_REQUESTS_PER_MINUTE) { break; @@ -71,32 +72,54 @@ class GitHubTask implements Runnable { Slimefun.getLogger().log(Level.WARNING, "Attempted to connect to mojang.com, got this response: {0}: {1}", new Object[] { x.getClass().getSimpleName(), x.getMessage() }); Slimefun.getLogger().log(Level.WARNING, "This usually means mojang.com is down or started to rate-limit this connection, this is not an error message!"); - // Retry after 4 minutes if it was rate-limiting + // Retry after 5 minutes if it was rate-limiting if (x.getMessage().contains("429")) { - Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 4 * 60 * 20L); + Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 5 * 60 * 20L); } - return; + + count = 0; + break; } catch (TooManyRequestsException x) { - Slimefun.getLogger().log(Level.WARNING, "Received a rate-limit from mojang.com, retrying in 2 minutes"); - Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 2 * 60 * 20L); - return; + Slimefun.getLogger().log(Level.WARNING, "Received a rate-limit from mojang.com, retrying in 4 minutes"); + Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 4 * 60 * 20L); + + count = 0; + break; } } } if (count >= MAX_REQUESTS_PER_MINUTE) { // Slow down API requests and wait a minute after more than x requests were made - Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 60 * 20L); + Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 2 * 60 * 20L); } + + for (GitHubConnector connector : gitHubService.getConnectors()) { + if (connector instanceof ContributionsConnector && !((ContributionsConnector) connector).hasFinished()) { + return; + } + } + + // We only wanna save this if all Connectors finished already + // This will run multiple times but thats okay, this way we get as much data as possible stored + gitHubService.saveUUIDCache(); } - private String grabTexture(Map skins, String username) throws TooManyRequestsException, IOException { - Optional uuid = MinecraftAccount.getUUID(username); + private String grabTexture(Map skins, Contributor contributor) throws TooManyRequestsException, IOException { + Optional uuid = contributor.getUniqueId(); + + if (!uuid.isPresent()) { + uuid = MinecraftAccount.getUUID(contributor.getMinecraftName()); + + if (uuid.isPresent()) { + contributor.setUniqueId(uuid.get()); + } + } if (uuid.isPresent()) { Optional skin = MinecraftAccount.getSkin(uuid.get()); - skins.put(username, skin.orElse("")); + skins.put(contributor.getMinecraftName(), skin.orElse("")); return skin.orElse(null); } else {