Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delayed database loading can cause duplicate items #15

Open
ikafly144 opened this issue Feb 13, 2025 · 0 comments
Open

Delayed database loading can cause duplicate items #15

ikafly144 opened this issue Feb 13, 2025 · 0 comments

Comments

@ikafly144
Copy link

After changes are made to the Vault on another server, if you move servers and open the Vault before the player has finished loading, you will see cached results. This allows for item duplication.
If you have a lot of items in your Vault that contain relatively large amounts of data, such as custom NBT, you can intentionally create delays in MySQL synchronization.
I am personally patching this to address this.
This fix doesn't take into account the delay when saving, but my server has a delay when moving between servers so that's not an issue.

Index: src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java b/src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java
--- a/src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java	(date 1739458691307)
@@ -6,6 +6,7 @@
 import com.artillexstudios.axvaults.database.Database;
 import com.artillexstudios.axvaults.placed.PlacedVaults;
 import com.artillexstudios.axvaults.utils.SerializationUtils;
+import com.artillexstudios.axvaults.utils.ThreadUtils;
 import com.artillexstudios.axvaults.utils.VaultUtils;
 import com.artillexstudios.axvaults.vaults.Vault;
 import org.bukkit.Bukkit;
@@ -15,11 +16,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
+import java.sql.*;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Consumer;
@@ -149,21 +146,28 @@
     }
 
     @Override
-    public void loadVaults(@NotNull UUID uuid) {
-        final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
-        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, uuid.toString());
+    public CompletableFuture<Void> loadVaults(@NotNull UUID uuid) {
+        CompletableFuture<Void> cf = new CompletableFuture<>();
+        Runnable runnable = () -> {
+            final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
+            try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+                stmt.setString(1, uuid.toString());
 
-            try (ResultSet rs = stmt.executeQuery()) {
-                while (rs.next()) {
-                    final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
-                    final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
-                    vault.setContents(items);
-                }
-            }
-        } catch (SQLException ex) {
-            ex.printStackTrace();
-        }
+                try (ResultSet rs = stmt.executeQuery()) {
+                    while (rs.next()) {
+                        final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
+                        final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
+                        vault.setContents(items);
+                    }
+                }
+                cf.complete(null);
+            } catch (SQLException ex) {
+                ex.printStackTrace();
+                cf.completeExceptionally(ex);
+            }
+        };
+        ThreadUtils.runSync(runnable);
+        return cf;
     }
 
     @Override
Index: src/main/java/com/artillexstudios/axvaults/database/impl/H2.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/database/impl/H2.java b/src/main/java/com/artillexstudios/axvaults/database/impl/H2.java
--- a/src/main/java/com/artillexstudios/axvaults/database/impl/H2.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/database/impl/H2.java	(date 1739458691320)
@@ -6,6 +6,7 @@
 import com.artillexstudios.axvaults.database.Database;
 import com.artillexstudios.axvaults.placed.PlacedVaults;
 import com.artillexstudios.axvaults.utils.SerializationUtils;
+import com.artillexstudios.axvaults.utils.ThreadUtils;
 import com.artillexstudios.axvaults.utils.VaultUtils;
 import com.artillexstudios.axvaults.vaults.Vault;
 import org.bukkit.Bukkit;
@@ -144,21 +145,28 @@
     }
 
     @Override
-    public void loadVaults(@NotNull UUID uuid) {
-        final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
-        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, uuid.toString());
+    public CompletableFuture<Void> loadVaults(@NotNull UUID uuid) {
+        CompletableFuture<Void> cf = new CompletableFuture<>();
+        Runnable runnable = () -> {
+            final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
+            try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+                stmt.setString(1, uuid.toString());
 
-            try (ResultSet rs = stmt.executeQuery()) {
-                while (rs.next()) {
-                    final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
-                    final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
-                    vault.setContents(items);
-                }
-            }
-        } catch (SQLException ex) {
-            ex.printStackTrace();
-        }
+                try (ResultSet rs = stmt.executeQuery()) {
+                    while (rs.next()) {
+                        final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
+                        final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
+                        vault.setContents(items);
+                    }
+                }
+                cf.complete(null);
+            } catch (SQLException ex) {
+                ex.printStackTrace();
+                cf.completeExceptionally(ex);
+            }
+        };
+        ThreadUtils.runSync(runnable);
+        return cf;
     }
 
     @Override
Index: src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java b/src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java
--- a/src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java	(date 1739459280714)
@@ -26,7 +26,7 @@
     }
 
     public void load() {
-        AxVaults.getDatabase().loadVaults(uuid);
+        AxVaults.getDatabase().loadVaults(uuid).join();
     }
 
     public ConcurrentHashMap<Integer, Vault> getVaultMap() {
Index: src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java b/src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java
--- a/src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java	(date 1739458639334)
@@ -3,6 +3,7 @@
 import com.artillexstudios.axapi.serializers.Serializers;
 import com.artillexstudios.axvaults.database.Database;
 import com.artillexstudios.axvaults.placed.PlacedVaults;
+import com.artillexstudios.axvaults.utils.ThreadUtils;
 import com.artillexstudios.axvaults.utils.VaultUtils;
 import com.artillexstudios.axvaults.vaults.Vault;
 import com.artillexstudios.axvaults.vaults.VaultManager;
@@ -16,11 +17,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
+import java.sql.*;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.UUID;
@@ -131,21 +128,28 @@
     }
 
     @Override
-    public void loadVaults(@NotNull UUID uuid) {
-        final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
-        try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, uuid.toString());
+    public CompletableFuture<Void> loadVaults(@NotNull UUID uuid) {
+        CompletableFuture<Void> cf = new CompletableFuture<>();
+        Runnable runnable = () -> {
+            final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
+            try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
+                stmt.setString(1, uuid.toString());
 
-            try (ResultSet rs = stmt.executeQuery()) {
-                while (rs.next()) {
-                    final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
-                    final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
-                    vault.setContents(items);
-                }
-            }
-        } catch (SQLException ex) {
-            ex.printStackTrace();
-        }
+                try (ResultSet rs = stmt.executeQuery()) {
+                    while (rs.next()) {
+                        final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
+                        final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
+                        vault.setContents(items);
+                    }
+                }
+                cf.complete(null);
+            } catch (SQLException ex) {
+                ex.printStackTrace();
+                cf.completeExceptionally(ex);
+            }
+        };
+        ThreadUtils.runSync(runnable);
+        return cf;
     }
 
     @Override
Index: src/main/java/com/artillexstudios/axvaults/database/Database.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/database/Database.java b/src/main/java/com/artillexstudios/axvaults/database/Database.java
--- a/src/main/java/com/artillexstudios/axvaults/database/Database.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/database/Database.java	(date 1739458515304)
@@ -16,7 +16,7 @@
 
     CompletableFuture<Void> saveVault(@NotNull Vault vault);
 
-    void loadVaults(@NotNull UUID uuid);
+    CompletableFuture<Void> loadVaults(@NotNull UUID uuid);
 
     boolean isVault(@NotNull Location location);
 
Index: src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java b/src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java
--- a/src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/database/impl/SQLite.java	(date 1739458691307)
@@ -6,6 +6,7 @@
 import com.artillexstudios.axvaults.database.Database;
 import com.artillexstudios.axvaults.placed.PlacedVaults;
 import com.artillexstudios.axvaults.utils.SerializationUtils;
+import com.artillexstudios.axvaults.utils.ThreadUtils;
 import com.artillexstudios.axvaults.utils.VaultUtils;
 import com.artillexstudios.axvaults.vaults.Vault;
 import org.bukkit.Bukkit;
@@ -15,11 +16,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
+import java.sql.*;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Consumer;
@@ -149,21 +146,28 @@
     }
 
     @Override
-    public void loadVaults(@NotNull UUID uuid) {
-        final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
-        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, uuid.toString());
+    public CompletableFuture<Void> loadVaults(@NotNull UUID uuid) {
+        CompletableFuture<Void> cf = new CompletableFuture<>();
+        Runnable runnable = () -> {
+            final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
+            try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+                stmt.setString(1, uuid.toString());
 
-            try (ResultSet rs = stmt.executeQuery()) {
-                while (rs.next()) {
-                    final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
-                    final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
-                    vault.setContents(items);
-                }
-            }
-        } catch (SQLException ex) {
-            ex.printStackTrace();
-        }
+                try (ResultSet rs = stmt.executeQuery()) {
+                    while (rs.next()) {
+                        final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
+                        final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
+                        vault.setContents(items);
+                    }
+                }
+                cf.complete(null);
+            } catch (SQLException ex) {
+                ex.printStackTrace();
+                cf.completeExceptionally(ex);
+            }
+        };
+        ThreadUtils.runSync(runnable);
+        return cf;
     }
 
     @Override
Index: src/main/java/com/artillexstudios/axvaults/database/impl/H2.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/database/impl/H2.java b/src/main/java/com/artillexstudios/axvaults/database/impl/H2.java
--- a/src/main/java/com/artillexstudios/axvaults/database/impl/H2.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/database/impl/H2.java	(date 1739458691320)
@@ -6,6 +6,7 @@
 import com.artillexstudios.axvaults.database.Database;
 import com.artillexstudios.axvaults.placed.PlacedVaults;
 import com.artillexstudios.axvaults.utils.SerializationUtils;
+import com.artillexstudios.axvaults.utils.ThreadUtils;
 import com.artillexstudios.axvaults.utils.VaultUtils;
 import com.artillexstudios.axvaults.vaults.Vault;
 import org.bukkit.Bukkit;
@@ -144,21 +145,28 @@
     }
 
     @Override
-    public void loadVaults(@NotNull UUID uuid) {
-        final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
-        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, uuid.toString());
+    public CompletableFuture<Void> loadVaults(@NotNull UUID uuid) {
+        CompletableFuture<Void> cf = new CompletableFuture<>();
+        Runnable runnable = () -> {
+            final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
+            try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+                stmt.setString(1, uuid.toString());
 
-            try (ResultSet rs = stmt.executeQuery()) {
-                while (rs.next()) {
-                    final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
-                    final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
-                    vault.setContents(items);
-                }
-            }
-        } catch (SQLException ex) {
-            ex.printStackTrace();
-        }
+                try (ResultSet rs = stmt.executeQuery()) {
+                    while (rs.next()) {
+                        final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
+                        final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
+                        vault.setContents(items);
+                    }
+                }
+                cf.complete(null);
+            } catch (SQLException ex) {
+                ex.printStackTrace();
+                cf.completeExceptionally(ex);
+            }
+        };
+        ThreadUtils.runSync(runnable);
+        return cf;
     }
 
     @Override
Index: src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java b/src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java
--- a/src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/vaults/VaultPlayer.java	(date 1739459280714)
@@ -26,7 +26,7 @@
     }
 
     public void load() {
-        AxVaults.getDatabase().loadVaults(uuid);
+        AxVaults.getDatabase().loadVaults(uuid).join();
     }
 
     public ConcurrentHashMap<Integer, Vault> getVaultMap() {
Index: src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java b/src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java
--- a/src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/database/impl/MySQL.java	(date 1739458639334)
@@ -3,6 +3,7 @@
 import com.artillexstudios.axapi.serializers.Serializers;
 import com.artillexstudios.axvaults.database.Database;
 import com.artillexstudios.axvaults.placed.PlacedVaults;
+import com.artillexstudios.axvaults.utils.ThreadUtils;
 import com.artillexstudios.axvaults.utils.VaultUtils;
 import com.artillexstudios.axvaults.vaults.Vault;
 import com.artillexstudios.axvaults.vaults.VaultManager;
@@ -16,11 +17,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
+import java.sql.*;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.UUID;
@@ -131,21 +128,28 @@
     }
 
     @Override
-    public void loadVaults(@NotNull UUID uuid) {
-        final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
-        try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, uuid.toString());
+    public CompletableFuture<Void> loadVaults(@NotNull UUID uuid) {
+        CompletableFuture<Void> cf = new CompletableFuture<>();
+        Runnable runnable = () -> {
+            final String sql = "SELECT * FROM axvaults_data WHERE uuid = ?;";
+            try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
+                stmt.setString(1, uuid.toString());
 
-            try (ResultSet rs = stmt.executeQuery()) {
-                while (rs.next()) {
-                    final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
-                    final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
-                    vault.setContents(items);
-                }
-            }
-        } catch (SQLException ex) {
-            ex.printStackTrace();
-        }
+                try (ResultSet rs = stmt.executeQuery()) {
+                    while (rs.next()) {
+                        final ItemStack[] items = Serializers.ITEM_ARRAY.deserialize(rs.getBytes(3));
+                        final Vault vault = new Vault(uuid, rs.getInt(1), rs.getString(4) == null ? null : Material.valueOf(rs.getString(4)));
+                        vault.setContents(items);
+                    }
+                }
+                cf.complete(null);
+            } catch (SQLException ex) {
+                ex.printStackTrace();
+                cf.completeExceptionally(ex);
+            }
+        };
+        ThreadUtils.runSync(runnable);
+        return cf;
     }
 
     @Override
Index: src/main/java/com/artillexstudios/axvaults/database/Database.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/artillexstudios/axvaults/database/Database.java b/src/main/java/com/artillexstudios/axvaults/database/Database.java
--- a/src/main/java/com/artillexstudios/axvaults/database/Database.java	(revision 388f3438375d9fa4837f8ea1e4c8ac3eb84ca09b)
+++ b/src/main/java/com/artillexstudios/axvaults/database/Database.java	(date 1739458515304)
@@ -16,7 +16,7 @@
 
     CompletableFuture<Void> saveVault(@NotNull Vault vault);
 
-    void loadVaults(@NotNull UUID uuid);
+    CompletableFuture<Void> loadVaults(@NotNull UUID uuid);
 
     boolean isVault(@NotNull Location location);
 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant