Optionally use a web cache for processing UUIDs

This commit is contained in:
turt2live 2014-08-31 21:09:03 -06:00
parent eac5d1ee7a
commit 735dbd667e
5 changed files with 141 additions and 9 deletions

12
pom.xml
View File

@ -78,6 +78,7 @@
<include>com.turt2live.metrics:MetricsExtension</include> <include>com.turt2live.metrics:MetricsExtension</include>
<include>commons-logging:commons-logging</include> <include>commons-logging:commons-logging</include>
<include>net.snaq:dbpool</include> <include>net.snaq:dbpool</include>
<include>com.turt2live:UUID-Library</include>
</includes> </includes>
</artifactSet> </artifactSet>
<relocations> <relocations>
@ -93,6 +94,10 @@
<pattern>net.snaq</pattern> <pattern>net.snaq</pattern>
<shadedPattern>com.gmail.nossr50.dbpool</shadedPattern> <shadedPattern>com.gmail.nossr50.dbpool</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>com.turt2live.uuid</pattern>
<shadedPattern>com.gmail.nossr50.uuid</shadedPattern>
</relocation>
</relocations> </relocations>
</configuration> </configuration>
<executions> <executions>
@ -123,7 +128,7 @@
<url>http://repo.md-5.net/content/repositories/releases/</url> <url>http://repo.md-5.net/content/repositories/releases/</url>
</repository> </repository>
<repository> <repository>
<id>Plugin MetricsExtension</id> <id>turt2live-repo</id>
<url>http://repo.turt2live.com</url> <url>http://repo.turt2live.com</url>
</repository> </repository>
</repositories> </repositories>
@ -151,6 +156,11 @@
<artifactId>dbpool</artifactId> <artifactId>dbpool</artifactId>
<version>5.1</version> <version>5.1</version>
</dependency> </dependency>
<dependency>
<groupId>com.turt2live</groupId>
<artifactId>UUID-Library</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
<distributionManagement> <distributionManagement>
<repository> <repository>

View File

@ -250,6 +250,7 @@ public class Config extends AutoUpdateConfigLoader {
public boolean getUpdateCheckEnabled() { return config.getBoolean("General.Update_Check", true); } public boolean getUpdateCheckEnabled() { return config.getBoolean("General.Update_Check", true); }
public boolean getPreferBeta() { return config.getBoolean("General.Prefer_Beta", false); } public boolean getPreferBeta() { return config.getBoolean("General.Prefer_Beta", false); }
public boolean getVerboseLoggingEnabled() { return config.getBoolean("General.Verbose_Logging", false); } public boolean getVerboseLoggingEnabled() { return config.getBoolean("General.Verbose_Logging", false); }
public boolean getUseUUIDWebCache(){ return config.getBoolean("General.Use_UUID_Web_Cache", false); }
public String getPartyChatPrefix() { return config.getString("Commands.partychat.Chat_Prefix_Format", "[[GREEN]]([[WHITE]]{0}[[GREEN]])"); } public String getPartyChatPrefix() { return config.getString("Commands.partychat.Chat_Prefix_Format", "[[GREEN]]([[WHITE]]{0}[[GREEN]])"); }
public boolean getPartyChatColorLeaderName() { return config.getBoolean("Commands.partychat.Gold_Leader_Name", true); } public boolean getPartyChatColorLeaderName() { return config.getBoolean("Commands.partychat.Gold_Leader_Name", true); }

View File

@ -13,9 +13,10 @@ import com.gmail.nossr50.config.HiddenConfig;
import com.gmail.nossr50.database.DatabaseManager; import com.gmail.nossr50.database.DatabaseManager;
import com.gmail.nossr50.datatypes.database.UpgradeType; import com.gmail.nossr50.datatypes.database.UpgradeType;
import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.uuid.UUIDFetcher; import com.gmail.nossr50.util.uuid.UUIDService;
public class UUIDUpdateAsyncTask extends BukkitRunnable { public class UUIDUpdateAsyncTask extends BukkitRunnable {
private mcMMO plugin; private mcMMO plugin;
private static final int MAX_LOOKUP = Math.max(HiddenConfig.getInstance().getUUIDConvertAmount(), 100); private static final int MAX_LOOKUP = Math.max(HiddenConfig.getInstance().getUUIDConvertAmount(), 100);
private static final int RATE_LIMIT = HiddenConfig.getInstance().getMojangRateLimit(); private static final int RATE_LIMIT = HiddenConfig.getInstance().getMojangRateLimit();
@ -25,6 +26,7 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
private List<String> userNames; private List<String> userNames;
private int size; private int size;
private int checkedUsers; private int checkedUsers;
private int fetchedUsers;
private long startMillis; private long startMillis;
public UUIDUpdateAsyncTask(mcMMO plugin, List<String> userNames) { public UUIDUpdateAsyncTask(mcMMO plugin, List<String> userNames) {
@ -32,12 +34,14 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
this.userNames = userNames; this.userNames = userNames;
this.checkedUsers = 0; this.checkedUsers = 0;
this.fetchedUsers = 0;
this.startMillis = System.currentTimeMillis(); this.startMillis = System.currentTimeMillis();
} }
@Override @Override
public void run() { public void run() {
size = userNames.size(); size = userNames.size();
UUIDService uuidService = null;
plugin.getLogger().info("Starting to check and update UUIDs, total amount of users: " + size); plugin.getLogger().info("Starting to check and update UUIDs, total amount of users: " + size);
@ -45,7 +49,7 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
Map<String, UUID> fetchedUUIDs = new HashMap<String, UUID>(); Map<String, UUID> fetchedUUIDs = new HashMap<String, UUID>();
while (size != 0) { while (size != 0) {
if (checkedUsers + 100 > RATE_LIMIT) { if (fetchedUsers + 100 > RATE_LIMIT) {
try { try {
Thread.sleep(LIMIT_PERIOD); Thread.sleep(LIMIT_PERIOD);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -53,25 +57,27 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
return; return;
} }
startMillis = System.currentTimeMillis(); startMillis = System.currentTimeMillis();
checkedUsers = 0; fetchedUsers = 0;
} }
if (size > MAX_LOOKUP) { if (size > MAX_LOOKUP) {
userNamesSection = userNames.subList(size - MAX_LOOKUP, size); userNamesSection = userNames.subList(size - MAX_LOOKUP, size);
size -= MAX_LOOKUP; size -= MAX_LOOKUP;
} } else {
else {
userNamesSection = userNames.subList(0, size); userNamesSection = userNames.subList(0, size);
size = 0; size = 0;
} }
try { try {
fetchedUUIDs.putAll(new UUIDFetcher(userNamesSection).call()); if (uuidService == null) uuidService = new UUIDService(userNamesSection);
} else uuidService.setList(userNamesSection);
catch (Exception e) {
fetchedUUIDs.putAll(uuidService.call());
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, "Unable to fetch UUIDs!", e); plugin.getLogger().log(Level.SEVERE, "Unable to fetch UUIDs!", e);
return; return;
} }
fetchedUsers += uuidService.getNumberFetched();
checkedUsers += userNamesSection.size(); checkedUsers += userNamesSection.size();
userNamesSection.clear(); userNamesSection.clear();
size = userNames.size(); size = userNames.size();

View File

@ -0,0 +1,111 @@
package com.gmail.nossr50.util.uuid;
import com.gmail.nossr50.config.Config;
import com.google.common.collect.ImmutableList;
import com.turt2live.uuid.CachingServiceProvider;
import com.turt2live.uuid.PlayerRecord;
import com.turt2live.uuid.ServiceProvider;
import com.turt2live.uuid.turt2live.v2.ApiV2Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Service layer for UUIDs
*
* @author turt2live
*/
public class UUIDService {
private static final int SERVICE_LIMIT_PER_REQUEST = 100;
private static ServiceProvider UUID_PROVIDER;
private List<String> names;
private int numFetched = 0; // From last request
/**
* Creates a new UUID service that takes a list of usernames
* to lookup via {@link #call()}
*
* @param names the names to lookup
*/
public UUIDService(List<String> names) {
this.names = ImmutableList.copyOf(names);
}
/**
* Sets a new list of names to parse
*
* @param names the names to lookup
*/
public void setList(List<String> names) {
this.names = ImmutableList.copyOf(names);
}
/**
* Parses the predefined list of names to a UUID map
*
* @return the generated map
*/
public Map<String, UUID> call() throws Exception {
int fetched = 0;
Map<String, UUID> map = new HashMap<String, UUID>();
if (Config.getInstance().getUseUUIDWebCache()) {
int requests = (int) Math.ceil(names.size() / SERVICE_LIMIT_PER_REQUEST);
for (int i = 0; i < requests; i++) {
List<String> subNames = names.subList(i * SERVICE_LIMIT_PER_REQUEST, Math.min((i + 1) * SERVICE_LIMIT_PER_REQUEST, names.size()));
List<PlayerRecord> records = UUID_PROVIDER.doBulkLookup(subNames.toArray(new String[subNames.size()]));
// List only includes successful lookups
for (PlayerRecord record : records) {
map.put(record.getName(), record.getUuid());
if (!record.isCached()) fetched++;
}
}
} else {
map = new UUIDFetcher(names).call();
fetched = map.size();
}
numFetched = fetched;
return map;
}
/**
* Gets the number of profiles that were actually fetched from the last
* call to {@link #call()}.
*
* @return the number of profiles actually fetched
*/
public int getNumberFetched() {
return numFetched;
}
/**
* Gets the UUID for the supplied username
*
* @param name the username to lookup, cannot be null
*
* @return the UUID, if found.
*
* @throws Exception thrown if something goes wrong
*/
public static UUID getUUIDOf(String name) throws Exception {
if (name == null) throw new IllegalArgumentException();
if (Config.getInstance().getUseUUIDWebCache()) {
if (UUID_PROVIDER == null) initProvider();
PlayerRecord record = UUID_PROVIDER.doLookup(name);
return record == null ? null : record.getUuid();
} else return UUIDFetcher.getUUIDOf(name);
}
private static void initProvider() {
UUID_PROVIDER = new CachingServiceProvider(new ApiV2Service());
}
}

View File

@ -26,6 +26,10 @@ General:
Config_Update_Overwrite: true Config_Update_Overwrite: true
# Play level-up sounds # Play level-up sounds
LevelUp_Sounds: true LevelUp_Sounds: true
# Instead of asking Mojang for UUIDs, should mcMMO access a web caching service
# for player UUIDs? If enabled, mcMMO will use the web service. If disabled, mcMMO
# will use Mojang.
Use_UUID_Web_Cache: false
# This should fix blocks being broken client side, but not server-side. # This should fix blocks being broken client side, but not server-side.
# Enable to refresh the chunks around a player at the end of Super Breaker, # Enable to refresh the chunks around a player at the end of Super Breaker,