Browse Source

Potential fix for loss of data due to SQL connection dropping

The idea behind this change is to send a ping every hour, which is shorter than the driver's 'dead connection' threshold of 8 hours.

As a side effect, this also will fix a subset of the situations where the MySQL server is restarted.
riking 11 years ago
parent
commit
f75fe3cc89

+ 3 - 0
src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java

@@ -24,6 +24,7 @@ import com.gmail.nossr50.datatypes.player.PlayerProfile;
 import com.gmail.nossr50.datatypes.skills.AbilityType;
 import com.gmail.nossr50.datatypes.skills.AbilityType;
 import com.gmail.nossr50.datatypes.skills.SkillType;
 import com.gmail.nossr50.datatypes.skills.SkillType;
 import com.gmail.nossr50.runnables.database.SQLReconnectTask;
 import com.gmail.nossr50.runnables.database.SQLReconnectTask;
+import com.gmail.nossr50.runnables.database.SQLDatabaseKeepaliveTask;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Misc;
 
 
 public final class SQLDatabaseManager implements DatabaseManager {
 public final class SQLDatabaseManager implements DatabaseManager {
@@ -51,6 +52,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
 
 
     protected SQLDatabaseManager() {
     protected SQLDatabaseManager() {
         checkStructure();
         checkStructure();
+
+        new SQLDatabaseKeepaliveTask(this).runTaskTimerAsynchronously(mcMMO.p, 10, 60L * 60 * Misc.TICK_CONVERSION_FACTOR);
     }
     }
 
 
     public void purgePowerlessUsers() {
     public void purgePowerlessUsers() {

+ 39 - 0
src/main/java/com/gmail/nossr50/runnables/database/SQLDatabaseKeepaliveTask.java

@@ -0,0 +1,39 @@
+package com.gmail.nossr50.runnables.database;
+
+import java.lang.ref.WeakReference;
+
+import org.bukkit.scheduler.BukkitRunnable;
+
+import com.gmail.nossr50.database.SQLDatabaseManager;
+
+/**
+ * This task is in charge of sending a MySQL ping over the MySQL connection
+ * every hour to prevent the connection from timing out and losing players'
+ * data when they join.
+ * <p>
+ * A WeakReference is used to keep the database instance, because
+ * {@link com.gmail.nossr50.commands.database.ConvertDatabaseCommand database
+ * conversion} may create a SQLDatabaseManager that will be thrown out. If a
+ * normal reference was used, the conversion would cause a combined data and
+ * resource leak through this task.
+ */
+public class SQLDatabaseKeepaliveTask extends BukkitRunnable {
+    WeakReference<SQLDatabaseManager> databaseInstance;
+
+    public SQLDatabaseKeepaliveTask(SQLDatabaseManager dbman) {
+        databaseInstance = new WeakReference<SQLDatabaseManager>(dbman);
+    }
+
+    public void run() {
+        SQLDatabaseManager dbman = databaseInstance.get();
+        if (dbman != null) {
+            dbman.checkConnected();
+        }
+        else {
+            // This happens when the database was started for a conversion,
+            // or discarded by its creator for any other reason. If this code
+            // was not present, we would leak the connection resources.
+            this.cancel();
+        }
+    }
+}