Skip to content

Commit

Permalink
Added API methods for direct database loads and saves #2396 (#2398)
Browse files Browse the repository at this point in the history
* Added API methods for direct database loads and saves #2396

* Fix test
  • Loading branch information
tastybento committed Jun 3, 2024
1 parent f68af55 commit 0938df8
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 19 deletions.
35 changes: 27 additions & 8 deletions src/main/java/world/bentobox/bentobox/managers/IslandsManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ public Island createIsland(@NonNull Location location, @Nullable UUID owner) {
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());
}
Expand Down Expand Up @@ -468,6 +468,16 @@ public Collection<Island> getIslands(@NonNull World world) {
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.
*
Expand Down Expand Up @@ -1448,7 +1458,7 @@ public void saveAll() {
}

/**
* 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
Expand All @@ -1458,7 +1468,7 @@ public void saveAll(boolean schedule) {
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());
}
Expand All @@ -1481,7 +1491,7 @@ public void run() {
}
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());
}
Expand Down Expand Up @@ -1516,7 +1526,7 @@ public void setLast(Location last) {
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.");
Expand Down Expand Up @@ -1636,7 +1646,7 @@ public void clearArea(Location loc) {
* @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));
}

Expand All @@ -1649,11 +1659,20 @@ public static void updateIsland(Island island) {
// 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
*
Expand Down
35 changes: 30 additions & 5 deletions src/main/java/world/bentobox/bentobox/managers/PlayersManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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;
Expand Down Expand Up @@ -81,17 +82,26 @@ private Players addPlayer(@NonNull UUID playerUUID) {
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.
Expand Down Expand Up @@ -382,4 +392,19 @@ public void cleanLeavingPlayer(World world, User target, boolean kicked, Island
}
}

/**
* 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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,15 @@ public Island getIslandAt(@NonNull Location location) {
/**
* 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.
*/
@NonNull
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);
}
Expand All @@ -286,6 +286,17 @@ public Collection<Island> getIslands() {
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.
Expand Down Expand Up @@ -317,7 +328,7 @@ public Collection<Island> getIslands(@NonNull World world) {

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);
}
Expand Down Expand Up @@ -461,7 +472,7 @@ public Island getIslandById(@NonNull String uniqueId, boolean cache) {
return island;
}

island = handler.loadObject(uniqueId);
island = loadIsland(uniqueId);
if (cache && island != null) {
islandsById.put(uniqueId, island);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,7 @@ public void testShutdown() {

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<>();
Expand Down Expand Up @@ -1085,7 +1085,7 @@ public void testClearRank() {

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<>();
Expand Down

0 comments on commit 0938df8

Please sign in to comment.