Added API methods for direct database loads and saves #2396 (#2398)

* Added API methods for direct database loads and saves #2396

* Fix test
This commit is contained in:
tastybento 2024-06-02 18:05:48 -07:00 committed by GitHub
parent f68af5529f
commit 0938df8824
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 19 deletions

View File

@ -254,7 +254,7 @@ public class IslandsManager {
island.setUniqueId(gmName + island.getUniqueId());
if (islandCache.addIsland(island)) {
// Save to database and notify other servers
handler.saveObjectAsync(island).thenAccept(b -> {
saveIsland(island).thenAccept(b -> {
if (b.equals(Boolean.TRUE)) {
MultiLib.notify("bentobox-newIsland", island.getUniqueId());
}
@ -468,6 +468,16 @@ public class IslandsManager {
return handler.loadObjects().stream().filter(i -> world.equals(i.getWorld())).toList();
}
/**
* Return island with uniqueId. Loads from database. Will block, so be careful.
* @param uniqueID id of island
* @return Optional Island object
* @since 2.4.0
*/
public Optional<Island> loadIsland(String uniqueID) {
return Optional.ofNullable(handler.loadObject(uniqueID));
}
/**
* Returns the IslandCache instance.
*
@ -1448,7 +1458,7 @@ public class IslandsManager {
}
/**
* Save the all the islands to the database
* Save the all the cached islands to the database
*
* @param schedule true if we should let the task run over multiple ticks to
* reduce lag spikes
@ -1458,7 +1468,7 @@ public class IslandsManager {
for (Island island : islandCache.getCachedIslands()) {
if (island.isChanged()) {
try {
handler.saveObjectAsync(island);
saveIsland(island);
} catch (Exception e) {
plugin.logError("Could not save island to database when running sync! " + e.getMessage());
}
@ -1481,7 +1491,7 @@ public class IslandsManager {
}
if (island.isChanged()) {
try {
handler.saveObjectAsync(island);
saveIsland(island);
} catch (Exception e) {
plugin.logError("Could not save island to database when running sync! " + e.getMessage());
}
@ -1516,7 +1526,7 @@ public class IslandsManager {
public void shutdown() {
plugin.log("Removing coops from islands...");
// Remove all coop associations
islandCache.getIslands().forEach(i -> i.getMembers().values().removeIf(p -> p == RanksManager.COOP_RANK));
islandCache.getCachedIslands().forEach(i -> i.getMembers().values().removeIf(p -> p == RanksManager.COOP_RANK));
plugin.log("Saving islands - this has to be done sync so it may take a while with a lot of islands...");
saveAll();
plugin.log("Islands saved.");
@ -1636,7 +1646,7 @@ public class IslandsManager {
* @param uniqueId - UUID of player
*/
public void clearRank(int rank, UUID uniqueId) {
islandCache.getIslands().forEach(
islandCache.getCachedIslands().forEach(
i -> i.getMembers().entrySet().removeIf(e -> e.getKey().equals(uniqueId) && e.getValue() == rank));
}
@ -1649,11 +1659,20 @@ public class IslandsManager {
// When mocking, handler can be null so this null check avoids errors
if (handler != null && handler.objectExists(island.getUniqueId())) {
island.clearChanged();
handler.saveObjectAsync(island)
.thenAccept(b -> MultiLib.notify("bentobox-updateIsland", island.getUniqueId()));
saveIsland(island).thenAccept(b -> MultiLib.notify("bentobox-updateIsland", island.getUniqueId()));
}
}
/**
* Saves the island async to the database
* @param island Island object to be saved
* @return CompletableFuture<Boolean> when done
* @since 2.4.0
*/
public static CompletableFuture<Boolean> saveIsland(Island island) {
return handler.saveObjectAsync(island);
}
/**
* Try to get an island by its unique id
*

View File

@ -7,6 +7,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.World;
@ -81,17 +82,26 @@ public class PlayersManager {
Objects.requireNonNull(playerUUID, "Player UUID must not be null");
// If the player exists in the database, load it; otherwise, create and save a new player
if (handler.objectExists(playerUUID.toString())) {
Players player = handler.loadObject(playerUUID.toString());
if (player != null) {
return player;
}
Players player = loadPlayer(playerUUID);
if (player != null) {
return player;
}
Players newPlayer = new Players(plugin, playerUUID);
handler.saveObjectAsync(newPlayer);
return newPlayer;
}
/**
* Force load the player from the database. The player must be known to BenoBox. If it is not
* use {@link #addPlayer(UUID)} instead. This is a blocking call, so be careful.
* @param uuid UUID of player
* @return Players object representing that player
* @since 2.4.0
*/
public @Nullable Players loadPlayer(UUID uuid) {
return handler.loadObject(uuid.toString());
}
/**
* Returns an <strong>unmodifiable collection</strong> of all the players that are <strong>currently in the cache</strong>.
* @return unmodifiable collection containing every player in the cache.
@ -382,4 +392,19 @@ public class PlayersManager {
}
}
/**
* Saves the player async to the database. The player has to be known to BentoBox to be saved.
* Players are usually detected by BentoBox when they join the server, so this is not an issue.
* @param uuid UUID of the player
* @return Completable future true when done, or false if not saved for some reason, e.g., invalid UUID
* @since 2.4.0
*/
public CompletableFuture<Boolean> savePlayer(UUID uuid) {
Players p = this.getPlayer(uuid);
if (p != null) {
return handler.saveObjectAsync(p);
}
return CompletableFuture.completedFuture(false);
}
}

View File

@ -269,7 +269,7 @@ public class IslandCache {
/**
* Returns an <strong>unmodifiable collection</strong> of all the islands (even
* those who may be unowned). Gets them from the cache or from the database if not
* loaded.
* loaded. This is a very heavy operation likely to cause lag.
*
* @return unmodifiable collection containing every island.
*/
@ -277,7 +277,7 @@ public class IslandCache {
public Collection<Island> getIslands() {
List<Island> result = new ArrayList<>();
for (Entry<@NonNull String, @NonNull Island> entry : islandsById.entrySet()) {
Island island = entry.getValue() != null ? entry.getValue() : handler.loadObject(entry.getKey());
Island island = entry.getValue() != null ? entry.getValue() : loadIsland(entry.getKey());
if (island != null) {
result.add(island);
}
@ -286,6 +286,17 @@ public class IslandCache {
return Collections.unmodifiableCollection(result);
}
/**
* Loads the island with the uniqueId from the database. Note, this could be a blocking call
* and lag the server, so be careful using it.
* @param uniqueId unique ID of the island
* @return Island or null if that uniqueID is unknown
* @since 2.4.0
*/
public Island loadIsland(String uniqueId) {
return handler.loadObject(uniqueId);
}
/**
* Returns an <strong>unmodifiable collection</strong> of all the islands (even
* those who may be unowned) that are cached.
@ -317,7 +328,7 @@ public class IslandCache {
List<Island> result = new ArrayList<>();
for (Entry<@NonNull String, @NonNull Island> entry : islandsById.entrySet()) {
Island island = entry.getValue() != null ? entry.getValue() : handler.loadObject(entry.getKey());
Island island = entry.getValue() != null ? entry.getValue() : loadIsland(entry.getKey());
if (island != null && overworld.equals(island.getWorld())) {
result.add(island);
}
@ -461,7 +472,7 @@ public class IslandCache {
return island;
}
island = handler.loadObject(uniqueId);
island = loadIsland(uniqueId);
if (cache && island != null) {
islandsById.put(uniqueId, island);
}

View File

@ -1045,7 +1045,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
Collection<Island> collection = new ArrayList<>();
collection.add(is);
when(islandCache.getIslands()).thenReturn(collection);
when(islandCache.getCachedIslands()).thenReturn(collection);
im.setIslandCache(islandCache);
Map<UUID, Integer> members = new HashMap<>();
@ -1085,7 +1085,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
Collection<Island> collection = new ArrayList<>();
collection.add(is);
when(islandCache.getIslands()).thenReturn(collection);
when(islandCache.getCachedIslands()).thenReturn(collection);
im.setIslandCache(islandCache);
Map<UUID, Integer> members = new HashMap<>();