From ca7a51af2cbf1806720caa35a2f220c09c6ee8c1 Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Fri, 1 Mar 2024 20:17:30 +0100 Subject: [PATCH] Permissions can now pre-cache all known players, and API users can get all cached players --- .../lib/permissions/DefaultPlayer.java | 2 +- .../pandacube/lib/permissions/PermGroup.java | 2 +- .../pandacube/lib/permissions/PermPlayer.java | 2 +- .../lib/permissions/Permissions.java | 24 ++++++++++++- .../PermissionsCachedBackendReader.java | 36 +++++++++++++++++-- 5 files changed, 59 insertions(+), 7 deletions(-) diff --git a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/DefaultPlayer.java b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/DefaultPlayer.java index 680de1b..459aee8 100644 --- a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/DefaultPlayer.java +++ b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/DefaultPlayer.java @@ -7,7 +7,7 @@ import java.util.UUID; /** * Represents a dummy player in the permission system, that have no specific data, only inheriting from the default * groups. - * + *

* The current implementation provides a player named {@code default.0} with an uuid of * {@code fffdef17-ffff-b0ff-ffff-ffffffffffff}. * Trying to set a permission data for this player will log a warning. diff --git a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermGroup.java b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermGroup.java index e2b7d63..c35026d 100644 --- a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermGroup.java +++ b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermGroup.java @@ -18,7 +18,7 @@ public final class PermGroup extends PermEntity { super(name, EntityType.Group); } @Override - protected CachedGroup getBackendEntity() { + /* package */ CachedGroup getBackendEntity() { return Permissions.backendReader.getCachedGroup(name); } diff --git a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermPlayer.java b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermPlayer.java index c96c75d..84c9f4f 100644 --- a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermPlayer.java +++ b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermPlayer.java @@ -17,7 +17,7 @@ public sealed class PermPlayer extends PermEntity permits DefaultPlayer { playerId = id; } @Override - protected CachedPlayer getBackendEntity() { + /* package */ CachedPlayer getBackendEntity() { return Permissions.backendReader.getCachedPlayer(playerId); } diff --git a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/Permissions.java b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/Permissions.java index 71ef016..89b0b06 100644 --- a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/Permissions.java +++ b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/Permissions.java @@ -104,9 +104,21 @@ public class Permissions { return new PermPlayer(playerId); } + /** + * Gets the permission object of all players stored in cache. + * @return the permission player object. + * @throws IllegalStateException if the permission system was not initialized properly. + */ + public static List getCachedPlayers() { + checkInitialized(); + return backendReader.getAllCachedPlayers().stream() + .map(cp -> getPlayer(cp.playerId)) + .toList(); + } + /** * Gets a dummy permission player object, that have no specific data, only inheriting from the default groups. - * + *

* The current implementation provides a player named {@code default.0} with an uuid of * {@code fffdef17-ffff-b0ff-ffff-ffffffffffff}. * Trying to set a permission data for this player will log a warning. @@ -137,6 +149,16 @@ public class Permissions { t.start(); } + /** + * Asks the permission system to preventively and asynchronously cache the data of all players. + * This method can be called before doing any operation involving most or all the permission data. + * @throws IllegalStateException if the permission system was not initialized properly. + */ + public static void precachePlayers() { + checkInitialized(); + backendReader.precacheAllPlayers(); + } + /** * Gets the permission group object. * @param name the name of the group. diff --git a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermissionsCachedBackendReader.java b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermissionsCachedBackendReader.java index c37ab12..70e442e 100644 --- a/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermissionsCachedBackendReader.java +++ b/pandalib-permissions/src/main/java/fr/pandacube/lib/permissions/PermissionsCachedBackendReader.java @@ -48,7 +48,7 @@ import fr.pandacube.lib.util.log.Log; /* package */ synchronized void clearPlayerCache(UUID playerId) { usersCache.invalidate(playerId); } - + /* package */ synchronized CachedPlayer getCachedPlayer(UUID playerId) { try { return usersCache.get(playerId, () -> { @@ -62,7 +62,32 @@ import fr.pandacube.lib.util.log.Log; throw new RuntimeException(e); } } - + + /* package */ synchronized List getAllCachedPlayers() { + return new ArrayList<>(usersCache.asMap().values()); + } + + /* package */ synchronized void precacheAllPlayers() { + try { + DB.getAll(SQLPermissions.class, SQLPermissions.type.eq(EntityType.User.getCode())) + .stream() + .collect(Collectors.groupingBy(el -> el.get(SQLPermissions.name), + Collectors.toCollection(() -> new SQLElementList()) + ) + ) + .forEach((idStr, pData) -> { + try { + UUID pId = UUID.fromString(idStr); + usersCache.put(pId, initPlayer(pId, pData)); + } catch (Exception e) { + Log.severe("Error caching player permission data (name=\"" + idStr + "\")", e); + } + }); + } catch (DBException e) { + throw new RuntimeException(e); + } + } + private CachedPlayer initPlayer(UUID playerId) throws DBException { if (playerId.equals(DEFAULT_PLAYER.playerId)) return DEFAULT_PLAYER; @@ -70,7 +95,12 @@ import fr.pandacube.lib.util.log.Log; SQLElementList playerData = DB.getAll(SQLPermissions.class, SQLPermissions.type.eq(EntityType.User.getCode()) .and(SQLPermissions.name.like(playerId.toString())) - ); + ); + + return initPlayer(playerId, playerData); + } + + private CachedPlayer initPlayer(UUID playerId, SQLElementList playerData) { Map> playerRawData = playerData.stream() .collect(