From 5a000add98be8f67370ab1b061cccabf71ed8205 Mon Sep 17 00:00:00 2001 From: William Date: Fri, 10 Mar 2023 21:00:15 +0000 Subject: [PATCH] Fix deadlock on busy servers with small thread pools, close #100 --- .../husksync/database/Database.java | 3 +- .../husksync/database/MySqlDatabase.java | 39 +++++++++---------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/common/src/main/java/net/william278/husksync/database/Database.java b/common/src/main/java/net/william278/husksync/database/Database.java index 6fb75be8..0dbff44e 100644 --- a/common/src/main/java/net/william278/husksync/database/Database.java +++ b/common/src/main/java/net/william278/husksync/database/Database.java @@ -114,10 +114,9 @@ public abstract class Database { * (Internal) Prune user data for a given user to the maximum value as configured. * * @param user The user to prune data for - * @return A future returning void when complete * @implNote Data snapshots marked as {@code pinned} are exempt from rotation */ - protected abstract CompletableFuture rotateUserData(@NotNull User user); + protected abstract void rotateUserData(@NotNull User user); /** * Deletes a specific {@link UserDataSnapshot} entry for a user from the database, by its UUID. diff --git a/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java b/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java index 9d2e3972..9680f4ca 100644 --- a/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java +++ b/common/src/main/java/net/william278/husksync/database/MySqlDatabase.java @@ -297,27 +297,25 @@ public class MySqlDatabase extends Database { } @Override - protected CompletableFuture rotateUserData(@NotNull User user) { - return CompletableFuture.runAsync(() -> { - final List unpinnedUserData = getUserData(user).join().stream() - .filter(dataSnapshot -> !dataSnapshot.pinned()).toList(); - if (unpinnedUserData.size() > plugin.getSettings().maxUserDataSnapshots) { - try (Connection connection = getConnection()) { - try (PreparedStatement statement = connection.prepareStatement(formatStatementTables(""" - DELETE FROM `%user_data_table%` - WHERE `player_uuid`=? - AND `pinned` IS FALSE - ORDER BY `timestamp` ASC - LIMIT %entry_count%;""".replace("%entry_count%", - Integer.toString(unpinnedUserData.size() - plugin.getSettings().maxUserDataSnapshots))))) { - statement.setString(1, user.uuid.toString()); - statement.executeUpdate(); - } - } catch (SQLException e) { - plugin.log(Level.SEVERE, "Failed to prune user data from the database", e); + protected void rotateUserData(@NotNull User user) { + final List unpinnedUserData = getUserData(user).join().stream() + .filter(dataSnapshot -> !dataSnapshot.pinned()).toList(); + if (unpinnedUserData.size() > plugin.getSettings().maxUserDataSnapshots) { + try (Connection connection = getConnection()) { + try (PreparedStatement statement = connection.prepareStatement(formatStatementTables(""" + DELETE FROM `%user_data_table%` + WHERE `player_uuid`=? + AND `pinned` IS FALSE + ORDER BY `timestamp` ASC + LIMIT %entry_count%;""".replace("%entry_count%", + Integer.toString(unpinnedUserData.size() - plugin.getSettings().maxUserDataSnapshots))))) { + statement.setString(1, user.uuid.toString()); + statement.executeUpdate(); } + } catch (SQLException e) { + plugin.log(Level.SEVERE, "Failed to prune user data from the database", e); } - }); + } } @Override @@ -362,7 +360,8 @@ public class MySqlDatabase extends Database { plugin.log(Level.SEVERE, "Failed to set user data in the database", e); } } - }).thenRun(() -> rotateUserData(user).join()); + this.rotateUserData(user); + }); } @Override