mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-26 18:11:29 +01:00
Optimized CleanTransaction inactive player query
- Removed SessionsTable#getLastSeenForAllPlayers - Made a test to ensure that the clean transaction does not delete all players - Fixed Peak player count fetch statement
This commit is contained in:
parent
6f474d2aea
commit
18cc7af151
@ -42,7 +42,8 @@ public class OptionalFetchQueries {
|
||||
public static Query<Optional<DateObj<Integer>>> fetchPeakPlayerCount(UUID serverUUID, long afterDate) {
|
||||
String sql = "SELECT " + TPSTable.DATE + ", MAX(" + TPSTable.PLAYERS_ONLINE + ") as max FROM " + TPSTable.TABLE_NAME +
|
||||
" WHERE " + TPSTable.SERVER_ID + "=" + ServerTable.STATEMENT_SELECT_SERVER_ID +
|
||||
" AND " + TPSTable.DATE + ">= ?";
|
||||
" AND " + TPSTable.DATE + ">= ?" +
|
||||
" GROUP BY " + TPSTable.SERVER_ID;
|
||||
|
||||
return new QueryStatement<Optional<DateObj<Integer>>>(sql) {
|
||||
@Override
|
||||
|
@ -19,9 +19,12 @@ package com.djrapitops.plan.db.access.transactions;
|
||||
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.OptionalFetchQueries;
|
||||
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.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||
@ -29,12 +32,12 @@ 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.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Transaction for cleaning up old data from the database.
|
||||
@ -64,7 +67,7 @@ public class CleanTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
Optional<Integer> allTimePeak = db.query(OptionalFetchQueries.fetchAllTimePeakPlayerCount(serverUUID)).map(DateObj::getValue);
|
||||
Optional<Integer> allTimePeak = query(OptionalFetchQueries.fetchAllTimePeakPlayerCount(serverUUID)).map(DateObj::getValue);
|
||||
|
||||
execute(cleanTPSTable(allTimePeak.orElse(-1)));
|
||||
execute(cleanPingTable());
|
||||
@ -79,10 +82,7 @@ public class CleanTransaction extends Transaction {
|
||||
long now = System.currentTimeMillis();
|
||||
long keepActiveAfter = now - keepInactiveForMs;
|
||||
|
||||
List<UUID> inactivePlayers = db.getSessionsTable().getLastSeenForAllPlayers().entrySet().stream()
|
||||
.filter(entry -> entry.getValue() < keepActiveAfter)
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
List<UUID> inactivePlayers = query(fetchInactivePlayerUUIDs(keepActiveAfter));
|
||||
for (UUID uuid : inactivePlayers) {
|
||||
executeOther(new RemovePlayerTransaction(uuid));
|
||||
}
|
||||
@ -118,4 +118,28 @@ 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -36,7 +36,7 @@ import java.sql.Savepoint;
|
||||
*/
|
||||
public abstract class Transaction {
|
||||
|
||||
SQLDB db;
|
||||
protected SQLDB db; // TODO Make private, this is a quick hack to access some tables while they are in use.
|
||||
|
||||
private Connection connection;
|
||||
private Savepoint savepoint;
|
||||
|
@ -188,27 +188,6 @@ public class SessionsTable extends Table {
|
||||
});
|
||||
}
|
||||
|
||||
public Map<UUID, Long> getLastSeenForAllPlayers() {
|
||||
String sql = "SELECT" +
|
||||
" MAX(" + SESSION_END + ") as last_seen, " +
|
||||
USER_UUID +
|
||||
" FROM " + tableName +
|
||||
" GROUP BY " + USER_UUID;
|
||||
|
||||
return query(new QueryAllStatement<Map<UUID, Long>>(sql, 20000) {
|
||||
@Override
|
||||
public Map<UUID, Long> processResults(ResultSet set) throws SQLException {
|
||||
Map<UUID, Long> lastSeenMap = new HashMap<>();
|
||||
while (set.next()) {
|
||||
UUID uuid = UUID.fromString(set.getString("uuid"));
|
||||
long lastSeen = set.getLong("last_seen");
|
||||
lastSeenMap.put(uuid, lastSeen);
|
||||
}
|
||||
return lastSeenMap;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Map<Integer, Integer> getIDServerIDRelation() {
|
||||
String sql = "SELECT " +
|
||||
ID + ", " +
|
||||
|
@ -132,6 +132,9 @@ public interface FetchOperations {
|
||||
@Deprecated
|
||||
Map<UUID, UserInfo> getUsers();
|
||||
|
||||
/**
|
||||
* @deprecated Now empty map is returned.
|
||||
*/
|
||||
@Deprecated
|
||||
Map<UUID, Long> getLastSeenForAllPlayers();
|
||||
|
||||
|
@ -110,7 +110,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
||||
|
||||
@Override
|
||||
public Map<UUID, Long> getLastSeenForAllPlayers() {
|
||||
return sessionsTable.getLastSeenForAllPlayers();
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,11 +48,13 @@ import com.djrapitops.plan.db.sql.tables.UsersTable;
|
||||
import com.djrapitops.plan.system.PlanSystem;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.config.Config;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
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 org.junit.*;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.rules.Timeout;
|
||||
@ -350,7 +352,7 @@ public abstract class CommonDBTest {
|
||||
saveTwoWorlds();
|
||||
saveUserOne();
|
||||
saveUserTwo();
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, "", "");
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, worlds[0], "SURVIVAL");
|
||||
session.endSession(22345L);
|
||||
session.setWorldTimes(createWorldTimes());
|
||||
session.setPlayerKills(createKills());
|
||||
@ -380,12 +382,11 @@ public abstract class CommonDBTest {
|
||||
saveUserOne();
|
||||
saveUserTwo();
|
||||
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, "", "");
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, worlds[0], "SURVIVAL");
|
||||
session.endSession(22345L);
|
||||
session.setWorldTimes(createWorldTimes());
|
||||
session.setPlayerKills(createKills());
|
||||
|
||||
SessionsTable sessionsTable = db.getSessionsTable();
|
||||
execute(DataStoreQueries.storeSession(session));
|
||||
|
||||
commitTest();
|
||||
@ -398,11 +399,6 @@ public abstract class CommonDBTest {
|
||||
assertNull(sessions.get(UUID.randomUUID()));
|
||||
|
||||
assertEquals(session, savedSessions.get(0));
|
||||
|
||||
Map<UUID, Long> lastSeen = sessionsTable.getLastSeenForAllPlayers();
|
||||
assertTrue(lastSeen.containsKey(playerUUID));
|
||||
assertFalse(lastSeen.containsKey(TestConstants.PLAYER_TWO_UUID));
|
||||
assertEquals(22345L, (long) lastSeen.get(playerUUID));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -475,12 +471,10 @@ public abstract class CommonDBTest {
|
||||
public void testRemovalSingleUser() {
|
||||
saveUserTwo();
|
||||
|
||||
SessionsTable sessionsTable = db.getSessionsTable();
|
||||
|
||||
db.executeTransaction(new PlayerServerRegisterTransaction(playerUUID, () -> 223456789L, "Test_name", serverUUID));
|
||||
saveTwoWorlds();
|
||||
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, "", "");
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, worlds[0], "SURVIVAL");
|
||||
session.endSession(22345L);
|
||||
session.setWorldTimes(createWorldTimes());
|
||||
session.setPlayerKills(createKills());
|
||||
@ -529,7 +523,7 @@ public abstract class CommonDBTest {
|
||||
|
||||
saveTwoWorlds();
|
||||
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, "", "");
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, worlds[0], "SURVIVAL");
|
||||
session.endSession(22345L);
|
||||
session.setWorldTimes(createWorldTimes());
|
||||
session.setPlayerKills(createKills());
|
||||
@ -580,22 +574,15 @@ public abstract class CommonDBTest {
|
||||
db.executeTransaction(new GeoInfoStoreTransaction(uuid, geoInfo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionTableNPEWhenNoPlayers() {
|
||||
Map<UUID, Long> lastSeen = db.getSessionsTable().getLastSeenForAllPlayers();
|
||||
assertTrue(lastSeen.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionTableGetInfoOfServer() throws DBInitException {
|
||||
saveUserOne();
|
||||
saveUserTwo();
|
||||
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, "", "");
|
||||
Session session = new Session(playerUUID, serverUUID, 12345L, worlds[0], "SURVIVAL");
|
||||
session.endSession(22345L);
|
||||
session.setWorldTimes(createWorldTimes());
|
||||
session.setPlayerKills(createKills());
|
||||
|
||||
execute(DataStoreQueries.storeSession(session));
|
||||
|
||||
commitTest();
|
||||
@ -609,6 +596,22 @@ public abstract class CommonDBTest {
|
||||
assertEquals(session, sSessions.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cleanTransactionDoesNotCleanActivePlayers() {
|
||||
saveUserOne();
|
||||
saveTwoWorlds();
|
||||
|
||||
long sessionStart = System.currentTimeMillis();
|
||||
Session session = new Session(playerUUID, serverUUID, sessionStart, worlds[0], "SURVIVAL");
|
||||
session.endSession(sessionStart + 22345L);
|
||||
execute(DataStoreQueries.storeSession(session));
|
||||
|
||||
db.executeTransaction(new CleanTransaction(serverUUID, TimeUnit.DAYS.toMillis(1L), new TestPluginLogger(), new Locale()));
|
||||
|
||||
Collection<BaseUser> found = db.query(BaseUserQueries.fetchServerBaseUsers(serverUUID));
|
||||
assertFalse("All users were deleted!! D:", found.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKillTableGetKillsOfServer() throws DBInitException {
|
||||
saveUserOne();
|
||||
|
Loading…
Reference in New Issue
Block a user