mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-27 03:27:37 +01:00
Fixed MySQL transaction timeout caused by CleanTask
This commit is contained in:
parent
fb7e752300
commit
52841f3724
@ -19,25 +19,14 @@ package com.djrapitops.plan.db.access.transactions.init;
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.db.access.ExecStatement;
|
||||
import com.djrapitops.plan.db.access.Executable;
|
||||
import com.djrapitops.plan.db.access.Query;
|
||||
import com.djrapitops.plan.db.access.QueryStatement;
|
||||
import com.djrapitops.plan.db.access.queries.objects.TPSQueries;
|
||||
import com.djrapitops.plan.db.access.transactions.Transaction;
|
||||
import com.djrapitops.plan.db.access.transactions.commands.RemovePlayerTransaction;
|
||||
import com.djrapitops.plan.db.sql.tables.PingTable;
|
||||
import com.djrapitops.plan.db.sql.tables.SessionsTable;
|
||||
import com.djrapitops.plan.db.sql.tables.TPSTable;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.results.RemoveUnsatisfiedConditionalResultsTransaction;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -46,25 +35,14 @@ import java.util.UUID;
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class CleanTransaction extends Transaction {
|
||||
public class RemoveOldSampledDataTransaction extends Transaction {
|
||||
|
||||
private final UUID serverUUID;
|
||||
|
||||
private final long keepInactiveForMs;
|
||||
|
||||
private final PluginLogger logger;
|
||||
private final Locale locale;
|
||||
|
||||
public CleanTransaction(
|
||||
UUID serverUUID,
|
||||
long keepInactiveForMs,
|
||||
PluginLogger logger,
|
||||
Locale locale
|
||||
public RemoveOldSampledDataTransaction(
|
||||
UUID serverUUID
|
||||
) {
|
||||
this.serverUUID = serverUUID;
|
||||
this.keepInactiveForMs = keepInactiveForMs;
|
||||
this.logger = logger;
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -73,25 +51,6 @@ public class CleanTransaction extends Transaction {
|
||||
|
||||
execute(cleanTPSTable(allTimePeak.orElse(-1)));
|
||||
execute(cleanPingTable());
|
||||
|
||||
// Clean DataExtension data
|
||||
executeOther(new RemoveUnsatisfiedConditionalResultsTransaction());
|
||||
|
||||
int removed = cleanOldPlayers();
|
||||
if (removed > 0) {
|
||||
logger.info(locale.getString(PluginLang.DB_NOTIFY_CLEAN, removed));
|
||||
}
|
||||
}
|
||||
|
||||
private int cleanOldPlayers() {
|
||||
long now = System.currentTimeMillis();
|
||||
long keepActiveAfter = now - keepInactiveForMs;
|
||||
|
||||
List<UUID> inactivePlayers = query(fetchInactivePlayerUUIDs(keepActiveAfter));
|
||||
for (UUID uuid : inactivePlayers) {
|
||||
executeOther(new RemovePlayerTransaction(uuid));
|
||||
}
|
||||
return inactivePlayers.size();
|
||||
}
|
||||
|
||||
private Executable cleanTPSTable(int allTimePlayerPeak) {
|
||||
@ -123,28 +82,4 @@ public class CleanTransaction extends Transaction {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Query<List<UUID>> fetchInactivePlayerUUIDs(long keepActiveAfter) {
|
||||
String sql = "SELECT uuid, last_seen FROM (SELECT" +
|
||||
" MAX(" + SessionsTable.SESSION_END + ") as last_seen, " + SessionsTable.USER_UUID +
|
||||
" FROM " + SessionsTable.TABLE_NAME +
|
||||
" GROUP BY " + SessionsTable.USER_UUID + ") as q1" +
|
||||
" WHERE last_seen < ?";
|
||||
return new QueryStatement<List<UUID>>(sql, 20000) {
|
||||
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setLong(1, keepActiveAfter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UUID> processResults(ResultSet set) throws SQLException {
|
||||
List<UUID> inactiveUUIDs = new ArrayList<>();
|
||||
while (set.next()) {
|
||||
inactiveUUIDs.add(UUID.fromString(set.getString("uuid")));
|
||||
}
|
||||
return inactiveUUIDs;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -18,19 +18,32 @@ package com.djrapitops.plan.db.tasks;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.db.Database;
|
||||
import com.djrapitops.plan.db.access.transactions.init.CleanTransaction;
|
||||
import com.djrapitops.plan.db.access.Query;
|
||||
import com.djrapitops.plan.db.access.QueryStatement;
|
||||
import com.djrapitops.plan.db.access.transactions.commands.RemovePlayerTransaction;
|
||||
import com.djrapitops.plan.db.access.transactions.init.RemoveOldSampledDataTransaction;
|
||||
import com.djrapitops.plan.db.sql.tables.SessionsTable;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.results.RemoveUnsatisfiedConditionalResultsTransaction;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.system.settings.paths.TimeSettings;
|
||||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Task for cleaning the active database.
|
||||
@ -70,13 +83,52 @@ public class DBCleanTask extends AbsRunnable {
|
||||
Database database = dbSystem.getDatabase();
|
||||
try {
|
||||
if (database.getState() != Database.State.CLOSED) {
|
||||
database.executeTransaction(new CleanTransaction(serverInfo.getServerUUID(),
|
||||
config.get(TimeSettings.KEEP_INACTIVE_PLAYERS), logger, locale)
|
||||
);
|
||||
database.executeTransaction(new RemoveOldSampledDataTransaction(serverInfo.getServerUUID()));
|
||||
database.executeTransaction(new RemoveUnsatisfiedConditionalResultsTransaction());
|
||||
int removed = cleanOldPlayers(database);
|
||||
if (removed > 0) {
|
||||
logger.info(locale.getString(PluginLang.DB_NOTIFY_CLEAN, removed));
|
||||
}
|
||||
}
|
||||
} catch (DBOpException e) {
|
||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public int cleanOldPlayers(Database database) {
|
||||
long now = System.currentTimeMillis();
|
||||
long keepActiveAfter = now - config.get(TimeSettings.KEEP_INACTIVE_PLAYERS);
|
||||
|
||||
List<UUID> inactivePlayers = database.query(fetchInactivePlayerUUIDs(keepActiveAfter));
|
||||
for (UUID uuid : inactivePlayers) {
|
||||
database.executeTransaction(new RemovePlayerTransaction(uuid));
|
||||
}
|
||||
return inactivePlayers.size();
|
||||
}
|
||||
|
||||
private Query<List<UUID>> fetchInactivePlayerUUIDs(long keepActiveAfter) {
|
||||
String sql = "SELECT uuid, last_seen FROM (SELECT" +
|
||||
" MAX(" + SessionsTable.SESSION_END + ") as last_seen, " + SessionsTable.USER_UUID +
|
||||
" FROM " + SessionsTable.TABLE_NAME +
|
||||
" GROUP BY " + SessionsTable.USER_UUID + ") as q1" +
|
||||
" WHERE last_seen < ?";
|
||||
return new QueryStatement<List<UUID>>(sql, 20000) {
|
||||
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setLong(1, keepActiveAfter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UUID> processResults(ResultSet set) throws SQLException {
|
||||
List<UUID> inactiveUUIDs = new ArrayList<>();
|
||||
while (set.next()) {
|
||||
inactiveUUIDs.add(UUID.fromString(set.getString("uuid")));
|
||||
}
|
||||
return inactiveUUIDs;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -42,10 +42,10 @@ import com.djrapitops.plan.db.access.transactions.StoreServerInformationTransact
|
||||
import com.djrapitops.plan.db.access.transactions.Transaction;
|
||||
import com.djrapitops.plan.db.access.transactions.commands.*;
|
||||
import com.djrapitops.plan.db.access.transactions.events.*;
|
||||
import com.djrapitops.plan.db.access.transactions.init.CleanTransaction;
|
||||
import com.djrapitops.plan.db.access.transactions.init.CreateIndexTransaction;
|
||||
import com.djrapitops.plan.db.access.transactions.init.CreateTablesTransaction;
|
||||
import com.djrapitops.plan.db.patches.Patch;
|
||||
import com.djrapitops.plan.db.tasks.DBCleanTask;
|
||||
import com.djrapitops.plan.extension.CallEvents;
|
||||
import com.djrapitops.plan.extension.DataExtension;
|
||||
import com.djrapitops.plan.extension.ExtensionServiceImplementation;
|
||||
@ -69,6 +69,7 @@ import com.djrapitops.plan.system.settings.paths.WebserverSettings;
|
||||
import com.djrapitops.plan.utilities.SHA256Hash;
|
||||
import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator;
|
||||
import com.djrapitops.plugin.logging.console.TestPluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ConsoleErrorLogger;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
@ -608,7 +609,7 @@ public abstract class CommonDBTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cleanTransactionDoesNotCleanActivePlayers() {
|
||||
public void cleanDoesNotCleanActivePlayers() {
|
||||
saveUserOne();
|
||||
saveTwoWorlds();
|
||||
|
||||
@ -617,7 +618,14 @@ public abstract class CommonDBTest {
|
||||
session.endSession(sessionStart + 22345L);
|
||||
execute(DataStoreQueries.storeSession(session));
|
||||
|
||||
db.executeTransaction(new CleanTransaction(serverUUID, TimeUnit.DAYS.toMillis(1L), new TestPluginLogger(), new Locale()));
|
||||
new DBCleanTask(
|
||||
system.getConfigSystem().getConfig(),
|
||||
new Locale(),
|
||||
system.getDatabaseSystem(),
|
||||
system.getServerInfo(),
|
||||
new TestPluginLogger(),
|
||||
new ConsoleErrorLogger(new TestPluginLogger())
|
||||
).cleanOldPlayers(db);
|
||||
|
||||
Collection<BaseUser> found = db.query(BaseUserQueries.fetchServerBaseUsers(serverUUID));
|
||||
assertFalse("All users were deleted!! D:", found.isEmpty());
|
||||
|
Loading…
Reference in New Issue
Block a user