mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-23 01:27:42 +01:00
Register plan_user row if missing when required
- PingStoreTransaction - GeoInfoStoreTransaction - SessionEndTransaction Affects issues: - Fixed #2361 - Fixed #2343
This commit is contained in:
parent
8cae81fb05
commit
6fa552ca5e
@ -29,6 +29,7 @@ import java.util.Optional;
|
||||
*/
|
||||
public class DBOpException extends IllegalStateException implements ExceptionWithContext {
|
||||
|
||||
public static final String CONSTRAINT_VIOLATION = "Constraint Violation";
|
||||
private final ErrorContext context;
|
||||
|
||||
public DBOpException(String message) {
|
||||
@ -101,7 +102,7 @@ public class DBOpException extends IllegalStateException implements ExceptionWit
|
||||
case 1364:
|
||||
case 1451:
|
||||
case 1557:
|
||||
context.related("Constraint Violation")
|
||||
context.related(CONSTRAINT_VIOLATION)
|
||||
.whatToDo("Report this, there is an SQL Constraint Violation.");
|
||||
break;
|
||||
// Custom rules based on reported errors
|
||||
@ -146,4 +147,10 @@ public class DBOpException extends IllegalStateException implements ExceptionWit
|
||||
public Optional<ErrorContext> getContext() {
|
||||
return Optional.ofNullable(context);
|
||||
}
|
||||
|
||||
public boolean isUserIdConstraintViolation() {
|
||||
return context != null
|
||||
&& context.getRelated().contains(DBOpException.CONSTRAINT_VIOLATION)
|
||||
&& getMessage().contains("user_id");
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -38,11 +39,13 @@ public class Identifiers {
|
||||
|
||||
protected final DBSystem dbSystem;
|
||||
private final UUIDUtility uuidUtility;
|
||||
private final ErrorLogger errorLogger;
|
||||
|
||||
@Inject
|
||||
public Identifiers(DBSystem dbSystem, UUIDUtility uuidUtility) {
|
||||
public Identifiers(DBSystem dbSystem, UUIDUtility uuidUtility, ErrorLogger errorLogger) {
|
||||
this.dbSystem = dbSystem;
|
||||
this.uuidUtility = uuidUtility;
|
||||
this.errorLogger = errorLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,6 +108,10 @@ public class Identifiers {
|
||||
return uuidUtility.getUUIDOf(name);
|
||||
}
|
||||
|
||||
public Optional<Integer> getPlayerUserId(UUID playerUUID) {
|
||||
return dbSystem.getDatabase().query(UserIdentifierQueries.fetchUserId(playerUUID));
|
||||
}
|
||||
|
||||
public static Optional<Long> getTimestamp(Request request) {
|
||||
try {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
@ -146,7 +146,7 @@ public class DataStoreQueries {
|
||||
* @param playerName Name of the player.
|
||||
* @return Executable, use inside a {@link com.djrapitops.plan.storage.database.transactions.Transaction}
|
||||
*/
|
||||
public static Executable registerBaseUser(UUID playerUUID, long registered, String playerName) {
|
||||
public static ExecStatement registerBaseUser(UUID playerUUID, long registered, String playerName) {
|
||||
return new ExecStatement(UsersTable.INSERT_STATEMENT) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
|
@ -218,4 +218,23 @@ public class UserIdentifierQueries {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Query<Optional<Integer>> fetchUserId(UUID playerUUID) {
|
||||
String sql = Select.from(UsersTable.TABLE_NAME, UsersTable.ID).where(UsersTable.USER_UUID + "=?").toString();
|
||||
|
||||
return new QueryStatement<Optional<Integer>>(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, playerUUID.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Integer> processResults(ResultSet set) throws SQLException {
|
||||
if (set.next()) {
|
||||
return Optional.of(set.getInt(UsersTable.ID));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.djrapitops.plan.storage.database.transactions.events;
|
||||
|
||||
import com.djrapitops.plan.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.gathering.domain.GeoInfo;
|
||||
import com.djrapitops.plan.storage.database.queries.DataStoreQueries;
|
||||
import com.djrapitops.plan.storage.database.transactions.Transaction;
|
||||
@ -72,6 +73,19 @@ public class GeoInfoStoreTransaction extends Transaction {
|
||||
protected void performOperations() {
|
||||
if (geoInfo == null) geoInfo = createGeoInfo();
|
||||
if (geoInfo.getGeolocation() == null) return; // Don't save null geolocation.
|
||||
try {
|
||||
execute(DataStoreQueries.storeGeoInfo(playerUUID, geoInfo));
|
||||
} catch (DBOpException failed) {
|
||||
if (failed.isUserIdConstraintViolation()) {
|
||||
retry();
|
||||
} else {
|
||||
throw failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void retry() {
|
||||
executeOther(new PlayerRegisterTransaction(playerUUID, System::currentTimeMillis, playerUUID.toString()));
|
||||
execute(DataStoreQueries.storeGeoInfo(playerUUID, geoInfo));
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
package com.djrapitops.plan.storage.database.transactions.events;
|
||||
|
||||
import com.djrapitops.plan.delivery.domain.DateObj;
|
||||
import com.djrapitops.plan.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.gathering.domain.Ping;
|
||||
import com.djrapitops.plan.identification.ServerUUID;
|
||||
import com.djrapitops.plan.storage.database.queries.DataStoreQueries;
|
||||
@ -48,6 +49,19 @@ public class PingStoreTransaction extends Transaction {
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
Ping ping = calculateAggregatePing();
|
||||
try {
|
||||
execute(DataStoreQueries.storePing(playerUUID, serverUUID, ping));
|
||||
} catch (DBOpException failed) {
|
||||
if (failed.isUserIdConstraintViolation()) {
|
||||
retry(ping);
|
||||
} else {
|
||||
throw failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void retry(Ping ping) {
|
||||
executeOther(new PlayerRegisterTransaction(playerUUID, System::currentTimeMillis, playerUUID.toString()));
|
||||
execute(DataStoreQueries.storePing(playerUUID, serverUUID, ping));
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import com.djrapitops.plan.storage.database.queries.DataStoreQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.PlayerFetchQueries;
|
||||
import com.djrapitops.plan.storage.database.transactions.Transaction;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
@ -36,6 +37,8 @@ public class PlayerRegisterTransaction extends Transaction {
|
||||
protected final LongSupplier registered;
|
||||
private final String playerName;
|
||||
|
||||
private Integer userId;
|
||||
|
||||
public PlayerRegisterTransaction(UUID playerUUID, LongSupplier registered, String playerName) {
|
||||
this.playerUUID = playerUUID;
|
||||
this.registered = registered;
|
||||
@ -54,12 +57,14 @@ public class PlayerRegisterTransaction extends Transaction {
|
||||
insertUser(registerDate);
|
||||
SessionCache.getCachedSession(playerUUID).ifPresent(session -> session.setAsFirstSessionIfMatches(registerDate));
|
||||
}
|
||||
execute(DataStoreQueries.updatePlayerName(playerUUID, playerName));
|
||||
if (!playerUUID.toString().equals(playerName)) {
|
||||
execute(DataStoreQueries.updatePlayerName(playerUUID, playerName));
|
||||
}
|
||||
}
|
||||
|
||||
private void insertUser(long registerDate) {
|
||||
try {
|
||||
execute(DataStoreQueries.registerBaseUser(playerUUID, registerDate, playerName));
|
||||
userId = executeReturningId(DataStoreQueries.registerBaseUser(playerUUID, registerDate, playerName));
|
||||
} catch (DBOpException failed) {
|
||||
boolean alreadySaved = failed.getMessage().contains("Duplicate entry");
|
||||
if (!alreadySaved) {
|
||||
@ -67,4 +72,8 @@ public class PlayerRegisterTransaction extends Transaction {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Integer> getUserId() {
|
||||
return Optional.ofNullable(userId);
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.djrapitops.plan.storage.database.transactions.events;
|
||||
|
||||
import com.djrapitops.plan.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.gathering.domain.FinishedSession;
|
||||
import com.djrapitops.plan.storage.database.queries.DataStoreQueries;
|
||||
import com.djrapitops.plan.storage.database.transactions.Transaction;
|
||||
@ -41,6 +42,20 @@ public class SessionEndTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
try {
|
||||
execute(DataStoreQueries.storeSession(session));
|
||||
} catch (DBOpException failed) {
|
||||
if (failed.isUserIdConstraintViolation()) {
|
||||
retry();
|
||||
} else {
|
||||
throw failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void retry() {
|
||||
UUID playerUUID = session.getPlayerUUID();
|
||||
executeOther(new PlayerRegisterTransaction(playerUUID, System::currentTimeMillis, playerUUID.toString()));
|
||||
execute(DataStoreQueries.storeSession(session));
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ import java.util.*;
|
||||
*/
|
||||
public class ErrorContext implements Serializable {
|
||||
|
||||
private final List<Object> related;
|
||||
private final transient List<Object> related;
|
||||
private String whatToDo;
|
||||
|
||||
private ErrorContext() {
|
||||
@ -55,6 +55,10 @@ public class ErrorContext implements Serializable {
|
||||
if (this.whatToDo == null && context.whatToDo != null) this.whatToDo = context.whatToDo;
|
||||
}
|
||||
|
||||
public List<Object> getRelated() {
|
||||
return related;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final ErrorContext context;
|
||||
|
||||
|
@ -182,8 +182,6 @@ public class PlayerOnlineListener implements FabricListener {
|
||||
Database database = dbSystem.getDatabase();
|
||||
database.executeTransaction(new WorldNameStoreTransaction(serverUUID, world));
|
||||
|
||||
InetSocketAddress socketAddress = (InetSocketAddress) player.networkHandler.connection.getAddress();
|
||||
InetAddress address = InetAddresses.forString(socketAddress.getAddress().toString().replace("/", ""));
|
||||
Supplier<String> getHostName = () -> getHostname(player);
|
||||
|
||||
String playerName = player.getEntityName();
|
||||
@ -195,9 +193,7 @@ public class PlayerOnlineListener implements FabricListener {
|
||||
.thenRunAsync(() -> {
|
||||
boolean gatheringGeolocations = config.isTrue(DataGatheringSettings.GEOLOCATIONS);
|
||||
if (gatheringGeolocations) {
|
||||
database.executeTransaction(
|
||||
new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry)
|
||||
);
|
||||
gatherGeolocation(player, playerUUID, time, database);
|
||||
}
|
||||
|
||||
database.executeTransaction(new OperatorStatusTransaction(playerUUID, serverUUID, server.getPlayerManager().getOpList().isOp(player.getGameProfile())));
|
||||
@ -220,6 +216,15 @@ public class PlayerOnlineListener implements FabricListener {
|
||||
});
|
||||
}
|
||||
|
||||
private void gatherGeolocation(ServerPlayerEntity player, UUID playerUUID, long time, Database database) {
|
||||
InetSocketAddress socketAddress = (InetSocketAddress) player.networkHandler.connection.getAddress();
|
||||
if (socketAddress == null) return;
|
||||
InetAddress address = InetAddresses.forString(socketAddress.getAddress().toString().replace("/", ""));
|
||||
database.executeTransaction(
|
||||
new GeoInfoStoreTransaction(playerUUID, address, time, geolocationCache::getCountry)
|
||||
);
|
||||
}
|
||||
|
||||
private String getHostname(ServerPlayerEntity player) {
|
||||
return joinAddresses.get(player.getUuid());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user