Transaction for storing World names.

Used on Gamemode change, World change or on join event.
This should ensure that the world name is stored when the session is
saved.
This commit is contained in:
Rsl1122 2019-01-28 21:39:57 +02:00
parent d095c791fb
commit 9e9196b181
11 changed files with 134 additions and 53 deletions

View File

@ -17,7 +17,10 @@
package com.djrapitops.plan.system.listeners.bukkit;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.db.access.transactions.events.WorldNameStoreTransaction;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.WorldAliasSettings;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.error.ErrorHandler;
@ -39,14 +42,20 @@ import java.util.UUID;
public class GameModeChangeListener implements Listener {
private final WorldAliasSettings worldAliasSettings;
private final ServerInfo serverInfo;
private final DBSystem dbSystem;
private final ErrorHandler errorHandler;
@Inject
public GameModeChangeListener(
WorldAliasSettings worldAliasSettings,
ServerInfo serverInfo,
DBSystem dbSystem,
ErrorHandler errorHandler
) {
this.worldAliasSettings = worldAliasSettings;
this.serverInfo = serverInfo;
this.dbSystem = dbSystem;
this.errorHandler = errorHandler;
}
@ -69,6 +78,7 @@ public class GameModeChangeListener implements Listener {
String gameMode = event.getNewGameMode().name();
String worldName = player.getWorld().getName();
dbSystem.getDatabase().executeTransaction(new WorldNameStoreTransaction(serverInfo.getServerUUID(), worldName));
worldAliasSettings.addWorld(worldName);
Optional<Session> cachedSession = SessionCache.getCachedSession(uuid);

View File

@ -17,7 +17,9 @@
package com.djrapitops.plan.system.listeners.bukkit;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.db.access.transactions.events.WorldNameStoreTransaction;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.processing.processors.Processors;
@ -51,6 +53,7 @@ public class PlayerOnlineListener implements Listener {
private final Processors processors;
private final Processing processing;
private final ServerInfo serverInfo;
private final DBSystem dbSystem;
private final SessionCache sessionCache;
private final ErrorHandler errorHandler;
private final Status status;
@ -62,6 +65,7 @@ public class PlayerOnlineListener implements Listener {
Processors processors,
Processing processing,
ServerInfo serverInfo,
DBSystem dbSystem,
SessionCache sessionCache,
Status status,
RunnableFactory runnableFactory,
@ -71,6 +75,7 @@ public class PlayerOnlineListener implements Listener {
this.processors = processors;
this.processing = processing;
this.serverInfo = serverInfo;
this.dbSystem = dbSystem;
this.sessionCache = sessionCache;
this.status = status;
this.runnableFactory = runnableFactory;
@ -135,6 +140,8 @@ public class PlayerOnlineListener implements Listener {
String world = player.getWorld().getName();
String gm = player.getGameMode().name();
dbSystem.getDatabase().executeTransaction(new WorldNameStoreTransaction(serverInfo.getServerUUID(), world));
InetAddress address = player.getAddress().getAddress();
String playerName = player.getName();

View File

@ -17,7 +17,10 @@
package com.djrapitops.plan.system.listeners.bukkit;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.db.access.transactions.events.WorldNameStoreTransaction;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.WorldAliasSettings;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.error.ErrorHandler;
@ -34,14 +37,20 @@ import java.util.UUID;
public class WorldChangeListener implements Listener {
private final WorldAliasSettings worldAliasSettings;
private final ServerInfo serverInfo;
private final DBSystem dbSystem;
private final ErrorHandler errorHandler;
@Inject
public WorldChangeListener(
WorldAliasSettings worldAliasSettings,
ServerInfo serverInfo,
DBSystem dbSystem,
ErrorHandler errorHandler
) {
this.worldAliasSettings = worldAliasSettings;
this.serverInfo = serverInfo;
this.dbSystem = dbSystem;
this.errorHandler = errorHandler;
}
@ -63,6 +72,7 @@ public class WorldChangeListener implements Listener {
String worldName = player.getWorld().getName();
String gameMode = player.getGameMode().name();
dbSystem.getDatabase().executeTransaction(new WorldNameStoreTransaction(serverInfo.getServerUUID(), worldName));
worldAliasSettings.addWorld(worldName);
Optional<Session> cachedSession = SessionCache.getCachedSession(uuid);

View File

@ -19,19 +19,13 @@ package com.djrapitops.plan.db.access.queries;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.data.time.GMTimes;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.db.access.ExecBatchStatement;
import com.djrapitops.plan.db.access.ExecStatement;
import com.djrapitops.plan.db.access.Executable;
import com.djrapitops.plan.db.sql.tables.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
/**
@ -94,7 +88,6 @@ public class DataStoreQueries {
return connection -> {
storeSessionInformation(session).execute(connection);
storeSessionKills(session).execute(connection);
storeSessionWorldTimesWorlds(session).execute(connection);
return storeSessionWorldTimes(session).execute(connection);
};
}
@ -123,50 +116,7 @@ public class DataStoreQueries {
};
}
// TODO Remove usage after WorldChange event stores world names in its own transaction
private static Executable storeSessionWorldTimesWorlds(Session session) {
return connection -> {
UUID serverUUID = session.getUnsafe(SessionKeys.SERVER_UUID);
Collection<String> worlds = session.getValue(SessionKeys.WORLD_TIMES)
.map(WorldTimes::getWorldTimes).map(Map::keySet)
.orElse(Collections.emptySet());
for (String world : worlds) {
storeWorldName(serverUUID, world).execute(connection);
}
return false;
};
}
// TODO Remove usage after WorldChange event stores world names in its own transaction
private static Executable storeWorldName(UUID serverUUID, String worldName) {
return connection -> {
if (!doesWorldNameExist(connection, serverUUID, worldName)) {
return insertWorldName(serverUUID, worldName).execute(connection);
}
return false;
};
}
// TODO Remove usage after WorldChange event stores world names in its own transaction
private static boolean doesWorldNameExist(Connection connection, UUID serverUUID, String worldName) {
String selectSQL = "SELECT COUNT(1) as c FROM " + WorldTable.TABLE_NAME +
" WHERE " + WorldTable.NAME + "=?" +
" AND " + WorldTable.SERVER_UUID + "=?";
try (PreparedStatement statement = connection.prepareStatement(selectSQL)) {
statement.setString(1, worldName);
statement.setString(2, serverUUID.toString());
try (ResultSet set = statement.executeQuery()) {
return set.next() && set.getInt("c") > 0;
}
} catch (SQLException ignored) {
// Assume it has been saved.
return true;
}
}
private static Executable insertWorldName(UUID serverUUID, String worldName) {
public static Executable insertWorldName(UUID serverUUID, String worldName) {
return new ExecStatement(WorldTable.INSERT_STATEMENT) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
@ -177,6 +127,9 @@ public class DataStoreQueries {
}
private static Executable storeSessionWorldTimes(Session session) {
if (session.getValue(SessionKeys.WORLD_TIMES).map(times -> times.getWorldTimes().isEmpty()).orElse(true)) {
return Executable.empty();
}
return new ExecBatchStatement(WorldTimesTable.INSERT_STATEMENT) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {

View File

@ -51,6 +51,8 @@ public abstract class Transaction {
Verify.nullCheck(db, () -> new IllegalArgumentException("Given database was null"));
Verify.isFalse(success, () -> new IllegalStateException("Transaction has already been executed"));
this.db = db;
if (!shouldBeExecuted()) {
return;
}
@ -83,7 +85,6 @@ public abstract class Transaction {
private void initializeTransaction(SQLDB db) {
try {
this.db = db;
this.connection = db.getConnection();
// Temporary fix for MySQL Patch task test failing, TODO remove after Auto commit is off for MySQL
if (connection.getAutoCommit()) connection.setAutoCommit(false);

View File

@ -0,0 +1,65 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.db.access.transactions.events;
import com.djrapitops.plan.db.access.HasMoreThanZeroQueryStatement;
import com.djrapitops.plan.db.access.queries.DataStoreQueries;
import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.db.sql.tables.WorldTable;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.UUID;
/**
* Transaction to store world name after an event.
*
* @author Rsl1122
*/
public class WorldNameStoreTransaction extends Transaction {
private final UUID serverUUID;
private final String worldName;
public WorldNameStoreTransaction(UUID serverUUID, String worldName) {
this.serverUUID = serverUUID;
this.worldName = worldName;
}
@Override
protected boolean shouldBeExecuted() {
return doesWorldNameNotExist();
}
private boolean doesWorldNameNotExist() {
String sql = "SELECT COUNT(1) as c FROM " + WorldTable.TABLE_NAME +
" WHERE " + WorldTable.NAME + "=?" +
" AND " + WorldTable.SERVER_UUID + "=?";
return !query(new HasMoreThanZeroQueryStatement(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, worldName);
statement.setString(2, serverUUID.toString());
}
});
}
@Override
protected void performOperations() {
execute(DataStoreQueries.insertWorldName(serverUUID, worldName));
}
}

View File

@ -34,6 +34,7 @@ import com.djrapitops.plan.db.access.queries.*;
import com.djrapitops.plan.db.access.queries.containers.ContainerFetchQueries;
import com.djrapitops.plan.db.access.transactions.*;
import com.djrapitops.plan.db.access.transactions.events.CommandStoreTransaction;
import com.djrapitops.plan.db.access.transactions.events.WorldNameStoreTransaction;
import com.djrapitops.plan.db.patches.Patch;
import com.djrapitops.plan.db.sql.tables.*;
import com.djrapitops.plan.system.PlanSystem;
@ -319,7 +320,10 @@ public abstract class CommonDBTest {
gm.put(gms[1], 2000L);
gm.put(gms[2], 3000L);
gm.put(gms[3], 4000L);
times.put(worlds.get(0), new GMTimes(gm));
String worldName = worlds.get(0);
times.put(worldName, new GMTimes(gm));
db.executeTransaction(new WorldNameStoreTransaction(serverUUID, worldName));
return new WorldTimes(times);
}
@ -667,6 +671,7 @@ public abstract class CommonDBTest {
"world",
GMTimes.getGMKeyArray()[0]
);
db.executeTransaction(new WorldNameStoreTransaction(serverUUID, "world"));
session.endSession(System.currentTimeMillis() + 1L);
return session;
}

View File

@ -20,6 +20,7 @@ import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.queries.DataStoreQueries;
import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.db.access.transactions.events.WorldNameStoreTransaction;
import com.djrapitops.plan.system.PlanSystem;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.settings.config.PlanConfig;
@ -83,12 +84,14 @@ public class JSErrorRegressionTest {
database.save().registerNewUser(uuid, 1000L, "TestPlayer");
Session session = new Session(uuid, TestConstants.SERVER_UUID, 1000L, "world", "SURVIVAL");
session.endSession(11000L);
database.executeTransaction(new WorldNameStoreTransaction(TestConstants.SERVER_UUID, "world"));
database.executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute(DataStoreQueries.storeSession(session));
}
});
// TODO Refactor to use Event transactions when available.
}

View File

@ -17,7 +17,10 @@
package com.djrapitops.plan.system.listeners.sponge;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.db.access.transactions.events.WorldNameStoreTransaction;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.WorldAliasSettings;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.error.ErrorHandler;
@ -38,14 +41,20 @@ import java.util.UUID;
public class SpongeGMChangeListener {
private final WorldAliasSettings worldAliasSettings;
private final ServerInfo serverInfo;
private final DBSystem dbSystem;
private ErrorHandler errorHandler;
@Inject
public SpongeGMChangeListener(
WorldAliasSettings worldAliasSettings,
ServerInfo serverInfo,
DBSystem dbSystem,
ErrorHandler errorHandler
) {
this.worldAliasSettings = worldAliasSettings;
this.serverInfo = serverInfo;
this.dbSystem = dbSystem;
this.errorHandler = errorHandler;
}
@ -70,6 +79,7 @@ public class SpongeGMChangeListener {
String gameMode = event.getGameMode().getName().toUpperCase();
String worldName = player.getWorld().getName();
dbSystem.getDatabase().executeTransaction(new WorldNameStoreTransaction(serverInfo.getServerUUID(), worldName));
worldAliasSettings.addWorld(worldName);
Optional<Session> cachedSession = SessionCache.getCachedSession(uuid);

View File

@ -17,7 +17,9 @@
package com.djrapitops.plan.system.listeners.sponge;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.db.access.transactions.events.WorldNameStoreTransaction;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.processing.Processing;
import com.djrapitops.plan.system.processing.processors.Processors;
@ -55,6 +57,7 @@ public class SpongePlayerListener {
private final Processors processors;
private final Processing processing;
private final ServerInfo serverInfo;
private final DBSystem dbSystem;
private SessionCache sessionCache;
private final Status status;
private RunnableFactory runnableFactory;
@ -66,6 +69,7 @@ public class SpongePlayerListener {
Processors processors,
Processing processing,
ServerInfo serverInfo,
DBSystem dbSystem,
SessionCache sessionCache,
Status status,
RunnableFactory runnableFactory,
@ -75,6 +79,7 @@ public class SpongePlayerListener {
this.processors = processors;
this.processing = processing;
this.serverInfo = serverInfo;
this.dbSystem = dbSystem;
this.sessionCache = sessionCache;
this.status = status;
this.runnableFactory = runnableFactory;
@ -140,6 +145,8 @@ public class SpongePlayerListener {
Optional<GameMode> gameMode = player.getGameModeData().get(Keys.GAME_MODE);
String gm = gameMode.map(mode -> mode.getName().toUpperCase()).orElse("ADVENTURE");
dbSystem.getDatabase().executeTransaction(new WorldNameStoreTransaction(serverInfo.getServerUUID(), world));
InetAddress address = player.getConnection().getAddress().getAddress();
String playerName = player.getName();

View File

@ -17,7 +17,10 @@
package com.djrapitops.plan.system.listeners.sponge;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.db.access.transactions.events.WorldNameStoreTransaction;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.WorldAliasSettings;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.error.ErrorHandler;
@ -41,14 +44,20 @@ import java.util.UUID;
public class SpongeWorldChangeListener {
private final WorldAliasSettings worldAliasSettings;
private final ServerInfo serverInfo;
private final DBSystem dbSystem;
private ErrorHandler errorHandler;
@Inject
public SpongeWorldChangeListener(
WorldAliasSettings worldAliasSettings,
ServerInfo serverInfo,
DBSystem dbSystem,
ErrorHandler errorHandler
) {
this.worldAliasSettings = worldAliasSettings;
this.serverInfo = serverInfo;
this.dbSystem = dbSystem;
this.errorHandler = errorHandler;
}
@ -73,6 +82,7 @@ public class SpongeWorldChangeListener {
String worldName = event.getToTransform().getExtent().getName();
String gameMode = getGameMode(player);
dbSystem.getDatabase().executeTransaction(new WorldNameStoreTransaction(serverInfo.getServerUUID(), worldName));
worldAliasSettings.addWorld(worldName);
Optional<Session> cachedSession = SessionCache.getCachedSession(uuid);