Warn about two servers storing data as same one

Affects issues:
- Close #2049
This commit is contained in:
Aurora Lahtela 2023-04-06 20:37:05 +03:00
parent e40793d2b8
commit ef7ddc0766
8 changed files with 65 additions and 1 deletions

View File

@ -20,6 +20,7 @@ import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.commands.use.Arguments;
import com.djrapitops.plan.commands.use.CMDSender;
import com.djrapitops.plan.gathering.listeners.Status;
import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.settings.locale.Locale;
import com.djrapitops.plan.settings.locale.lang.CommandLang;
import com.djrapitops.plan.settings.locale.lang.GenericLang;
@ -41,6 +42,7 @@ public class PluginStatusCommands {
private final PlanPlugin plugin;
private final PluginInformation pluginInformation;
private final Locale locale;
private final ServerInfo serverInfo;
private final DBSystem dbSystem;
private final Status status;
private final VersionChecker versionChecker;
@ -51,6 +53,7 @@ public class PluginStatusCommands {
PlanPlugin plugin,
PluginInformation pluginInformation,
Locale locale,
ServerInfo serverInfo,
DBSystem dbSystem,
Status status,
VersionChecker versionChecker,
@ -59,6 +62,7 @@ public class PluginStatusCommands {
this.plugin = plugin;
this.pluginInformation = pluginInformation;
this.locale = locale;
this.serverInfo = serverInfo;
this.dbSystem = dbSystem;
this.status = status;
this.versionChecker = versionChecker;
@ -113,6 +117,7 @@ public class PluginStatusCommands {
locale.getString(CommandLang.INFO_UPDATE, updateAvailable),
locale.getString(CommandLang.INFO_DATABASE, database.getType().getName() + " (" + database.getState().name() + ")"),
locale.getString(CommandLang.INFO_PROXY_CONNECTION, proxyAvailable),
locale.getString(CommandLang.INFO_SERVER_UUID, serverInfo.getServerUUID()),
"",
">"
};

View File

@ -84,6 +84,7 @@ public class ProxyTPSCounter extends TPSCounter {
long freeDiskSpace = systemUsage.getFreeDiskSpace();
dbSystem.getDatabase().executeTransaction(new TPSStoreTransaction(
logger,
serverInfo.getServerUUID(),
TPSBuilder.get()
.date(timeLastMinute)

View File

@ -101,6 +101,7 @@ public class ServerTPSCounter<W> extends TPSCounter {
long freeDiskSpace = systemUsage.getFreeDiskSpace();
dbSystem.getDatabase().executeTransaction(new TPSStoreTransaction(
logger,
serverInfo.getServerUUID(),
TPSBuilder.get()
.date(timeLastMinute)

View File

@ -88,6 +88,7 @@ public enum CommandLang implements Lang {
INFO_UPDATE("command.subcommand.info.update", "Cmd Info - Update", " §2Update Available: §f${0}"),
INFO_DATABASE("command.subcommand.info.database", "Cmd Info - Database", " §2Current Database: §f${0}"),
INFO_PROXY_CONNECTION("command.subcommand.info.proxy", "Cmd Info - Bungee Connection", " §2Connected to Proxy: §f${0}"),
INFO_SERVER_UUID("command.subcommand.info.serverUUID", "Cmd Info - Server UUID", " §2Server UUID: §f${0}"),
INGAME_ACTIVITY_INDEX("command.ingame.activityIndex", "Cmd Qinspect - Activity Index", " §2Activity Index: §f${0} | ${1}"),
INGAME_REGISTERED("command.ingame.registered", "Cmd Qinspect - Registered", " §2Registered: §f${0}"),

View File

@ -25,6 +25,7 @@ import com.djrapitops.plan.storage.database.queries.QueryStatement;
import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
import com.djrapitops.plan.utilities.dev.Benchmark;
import com.djrapitops.plan.utilities.java.Lists;
import org.intellij.lang.annotations.Language;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -453,6 +454,12 @@ public class TPSQueries {
};
}
public static Query<Optional<Long>> fetchLastStoredTpsDate(ServerUUID serverUUID) {
@Language("SQL")
String sql = "SELECT MAX(date) FROM plan_tps WHERE server_id=" + ServerTable.SELECT_SERVER_ID;
return db -> db.queryOptional(sql, resultSet -> resultSet.getLong(1), serverUUID);
}
public static Query<Map<Integer, List<TPS>>> fetchTPSDataOfServers(long after, long before, Collection<ServerUUID> serverUUIDs) {
String sql = SELECT + "*" + FROM + TABLE_NAME +
WHERE + SERVER_ID + " IN " + ServerTable.selectServerIds(serverUUIDs) +

View File

@ -19,7 +19,11 @@ package com.djrapitops.plan.storage.database.transactions.events;
import com.djrapitops.plan.gathering.domain.TPS;
import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.queries.DataStoreQueries;
import com.djrapitops.plan.storage.database.queries.objects.TPSQueries;
import com.djrapitops.plan.storage.database.transactions.Transaction;
import net.playeranalytics.plugin.server.PluginLogger;
import java.util.concurrent.TimeUnit;
/**
* Transaction to store server's TPS data.
@ -28,16 +32,45 @@ import com.djrapitops.plan.storage.database.transactions.Transaction;
*/
public class TPSStoreTransaction extends Transaction {
private static long lastStorageCheck = 0L;
private final PluginLogger logger;
private final ServerUUID serverUUID;
private final TPS tps;
public TPSStoreTransaction(PluginLogger logger, ServerUUID serverUUID, TPS tps) {
this.serverUUID = serverUUID;
this.tps = tps;
this.logger = logger;
}
public TPSStoreTransaction(ServerUUID serverUUID, TPS tps) {
this.serverUUID = serverUUID;
this.tps = tps;
logger = null;
}
public static void setLastStorageCheck(long lastStorageCheck) {
TPSStoreTransaction.lastStorageCheck = lastStorageCheck;
}
@Override
protected void performOperations() {
long now = System.currentTimeMillis();
if (logger != null && now - lastStorageCheck > TimeUnit.MINUTES.toMillis(30)) {
performDuplicateServerUUIDServerCheck(now);
TPSStoreTransaction.setLastStorageCheck(now);
}
execute(DataStoreQueries.storeTPS(serverUUID, tps));
}
private void performDuplicateServerUUIDServerCheck(long now) {
Long lastStoredData = query(TPSQueries.fetchLastStoredTpsDate(serverUUID)).orElse(0L);
long diff = now - lastStoredData;
if (logger != null && diff > TimeUnit.SECONDS.toMillis(30)) {
logger.warn("Database had TPS data which was stored " + diff + "ms ago, this is a sign that two servers are storing data as " + serverUUID +
" - Check that you have not copied /plugins/Plan/ServerInfoFile.yml between two servers. (This warning will show on both servers)");
}
}
}

View File

@ -81,7 +81,7 @@ public class CorrectWrongCharacterEncodingPatch extends Patch {
")";
@Language("MySQL")
String sql = selectTablesWithWrongCharset + " UNION " + selectColumnsWithWrongCharset;
return db -> db.queryList(sql, resultSet -> resultSet.getString(0));
return db -> db.queryList(sql, resultSet -> resultSet.getString(1));
}
@Override

View File

@ -26,7 +26,9 @@ import com.djrapitops.plan.storage.database.transactions.commands.RemoveEverythi
import com.djrapitops.plan.storage.database.transactions.events.TPSStoreTransaction;
import com.djrapitops.plan.utilities.comparators.TPSComparator;
import com.djrapitops.plan.utilities.java.Lists;
import net.playeranalytics.plugin.server.PluginLogger;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import utilities.RandomData;
import java.util.Comparator;
@ -36,6 +38,9 @@ import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
public interface TPSQueriesTest extends DatabaseTestPreparer {
@ -73,6 +78,17 @@ public interface TPSQueriesTest extends DatabaseTestPreparer {
assertEquals(expected, actual, () -> "Wrong return value. " + Lists.map(tpsData, TPS::getPlayers).toString());
}
@Test
default void sameServerIsDetected() {
TPS tps = RandomData.randomTPS().get(0);
PluginLogger logger = Mockito.mock(PluginLogger.class);
db().executeTransaction(new TPSStoreTransaction(logger, serverUUID(), tps));
db().executeTransaction(new TPSStoreTransaction(logger, serverUUID(), tps));
db().executeTransaction(new TPSStoreTransaction(logger, serverUUID(), tps));
verify(logger, times(1)).warn(anyString());
}
@Test
default void serverStartDateIsFetched() {
List<TPS> tpsData = RandomData.randomTPS();