Fix some concurrency issues with login handling

This commit is contained in:
Luck
2017-03-26 18:40:09 +01:00
Unverified
parent 486b19aa90
commit 8e557d122b
14 changed files with 375 additions and 165 deletions
@@ -27,6 +27,7 @@ import lombok.Getter;
import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.commands.utils.Util;
import me.lucko.luckperms.common.locale.LocaleManager;
@SuppressWarnings("SpellCheckingInspection")
@AllArgsConstructor
@@ -44,7 +45,7 @@ public enum Message {
EMPTY("{0}", true),
PLAYER_ONLINE("&aOnline", false),
PLAYER_OFFLINE("&cOffline", false),
LOADING_ERROR("Permissions data could not be loaded. Please contact an administrator.", true),
LOADING_ERROR("Permissions data could not be loaded. Please try again later.", true),
OP_DISABLED("&bThe vanilla OP system is disabled on this server.", false),
OP_DISABLED_SPONGE("&2Server Operator status has no effect when a permission plugin is installed. Please edit user data directly.", true),
LOG("&3LOG &3&l> {0}", true),
@@ -452,6 +453,21 @@ public enum Message {
return Util.color(showPrefix ? PREFIX + message : message);
}
public String asString(LocaleManager localeManager) {
String prefix = localeManager.getTranslation(PREFIX);
if (prefix == null) {
prefix = PREFIX.getMessage();
}
String s = localeManager.getTranslation(this);
if (s == null) {
s = message;
}
s = s.replace("{PREFIX}", prefix).replace("\\n", "\n");
return Util.color(showPrefix ? (prefix + s) : (s));
}
public void send(Sender sender, Object... objects) {
String prefix = sender.getPlatform().getLocaleManager().getTranslation(PREFIX);
if (prefix == null) {
@@ -60,6 +60,13 @@ public interface UserManager extends Manager<UserIdentifier, User> {
*/
void cleanup(User user);
/**
* Schedules a task to cleanup a user after a certain period of time, if they're not on the server anymore.
*
* @param uuid external uuid of the player
*/
void scheduleUnload(UUID uuid);
/**
* Reloads the data of all online users
*/
@@ -134,6 +134,18 @@ public class GenericUserManager extends AbstractManager<UserIdentifier, User> im
}
}
@Override
public void scheduleUnload(UUID uuid) {
plugin.getScheduler().doAsyncLater(() -> {
User user = get(plugin.getUuidCache().getUUID(uuid));
if (user != null && !plugin.isPlayerOnline(uuid)) {
user.unregisterData();
unload(user);
}
plugin.getUuidCache().clearCache(uuid);
}, 40L);
}
@Override
public void updateAllUsers() {
plugin.doSync(() -> {
@@ -22,7 +22,7 @@
package me.lucko.luckperms.common.utils;
import lombok.AllArgsConstructor;
import lombok.experimental.UtilityClass;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.core.UuidCache;
@@ -33,13 +33,12 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import java.util.UUID;
/**
* An abstract listener shared by Bukkit & Sponge.
* Utilities for use in platform listeners
*/
@AllArgsConstructor
public class AbstractListener {
private final LuckPermsPlugin plugin;
@UtilityClass
public class LoginHelper {
public void onAsyncLogin(UUID u, String username) {
public static void loadUser(LuckPermsPlugin plugin, UUID u, String username) {
final long startTime = System.currentTimeMillis();
final UuidCache cache = plugin.getUuidCache();
@@ -67,6 +66,7 @@ public class AbstractListener {
User user = plugin.getUserManager().get(cache.getUUID(u));
if (user == null) {
plugin.getLog().warn("Failed to load user: " + username);
throw new RuntimeException("Failed to load user");
} else {
// Setup defaults for the user
boolean save = false;
@@ -90,20 +90,7 @@ public class AbstractListener {
}
}
protected void onLeave(UUID uuid) {
final UuidCache cache = plugin.getUuidCache();
final User user = plugin.getUserManager().get(cache.getUUID(uuid));
if (user != null) {
user.unregisterData();
plugin.getUserManager().unload(user);
}
// Unload the user from memory when they disconnect;
cache.clearCache(uuid);
}
protected void refreshPlayer(UUID uuid) {
public static void refreshPlayer(LuckPermsPlugin plugin, UUID uuid) {
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(uuid));
if (user != null) {
user.getRefreshBuffer().requestDirectly();