From 4c8c2e53e2e2ef153438f771ced5c27b2e58139c Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sat, 26 Oct 2024 16:49:19 +0200 Subject: [PATCH 01/43] Start working on new database system --- build.gradle.kts | 3 + .../database/AbstractDatabaseService.java | 3 + .../database/DatabaseManager.java | 118 ++++++++++++++++++ .../parcellockers/database/DatabaseType.java | 5 +- .../database/persister/PositionPersister.java | 67 ++++++++++ .../wrapper/AbstractRepositoryOrmLite.java | 72 +++++++++++ .../parcellockers/shared/Position.java | 2 +- 7 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java create mode 100644 src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java create mode 100644 src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java diff --git a/build.gradle.kts b/build.gradle.kts index e07b4e42..7e99c162 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -57,6 +57,9 @@ dependencies { // database implementation("com.zaxxer:HikariCP:6.0.0") + implementation("com.j256.ormlite:ormlite-jdbc:6.1") + implementation("com.h2database:h2:2.3.232") + implementation("org.postgresql:postgresql:42.7.4") // lombok compileOnly("org.projectlombok:lombok:1.18.34") diff --git a/src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java b/src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java index d36c5b0a..e74a7e44 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java +++ b/src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java @@ -34,6 +34,7 @@ protected AbstractDatabaseService(DataSource dataSource) { this.dataSource = dataSource; } + // for void-like (removing, inserting, updating) protected CompletableFuture execute(String sql, ThrowingConsumer consumer) { return this.supplyExecute(sql, statement -> { consumer.accept(statement); @@ -41,6 +42,7 @@ protected CompletableFuture execute(String sql, ThrowingConsumer CompletableFuture supplyExecute(String sql, ThrowingFunction function) { return CompletableFuture.supplyAsync(() -> { try (Connection connection = this.dataSource.getConnection(); @@ -54,6 +56,7 @@ protected CompletableFuture supplyExecute(String sql, ThrowingFunction T executeSync(String sql, ThrowingFunction function) { try (Connection connection = this.dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(sql) diff --git a/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java b/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java new file mode 100644 index 00000000..59251429 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java @@ -0,0 +1,118 @@ +package com.eternalcode.parcellockers.database; + +import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; +import com.google.common.base.Stopwatch; +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.dao.DaoManager; +import com.j256.ormlite.jdbc.DataSourceConnectionSource; +import com.j256.ormlite.support.ConnectionSource; +import com.zaxxer.hikari.HikariDataSource; + +import java.io.File; +import java.sql.SQLException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +public class DatabaseManager { + + private final PluginConfiguration config; + private final Logger logger; + + private final File dataFolder; + private final Map, Dao> cachedDao = new ConcurrentHashMap<>(); + + private HikariDataSource dataSource; + private ConnectionSource connectionSource; + + public DatabaseManager(PluginConfiguration config, Logger logger, File dataFolder) { + this.config = config; + this.logger = logger; + this.dataFolder = dataFolder; + } + + public void connect() throws SQLException { + Stopwatch stopwatch = Stopwatch.createStarted(); + + DatabaseType databaseType = this.config.settings.databaseType; + + this.dataSource = new HikariDataSource(); + + this.dataSource.addDataSourceProperty("cachePrepStmts", true); + this.dataSource.addDataSourceProperty("prepStmtCacheSize", 250); + this.dataSource.addDataSourceProperty("prepStmtCacheSqlLimit", 2048); + this.dataSource.addDataSourceProperty("useServerPrepStmts", true); + + this.dataSource.setMaximumPoolSize(5); + this.dataSource.setUsername(this.config.settings.user); + this.dataSource.setPassword(this.config.settings.password); + + switch (DatabaseType.valueOf(databaseType.toString().toUpperCase())) { + + case MYSQL -> { + this.dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); + this.dataSource.setJdbcUrl("jdbc:mysql://" + this.config.settings.host + ":" + this.config.settings.port + "/" + this.config.settings.databaseName); + } + + case MARIADB -> { + this.dataSource.setDriverClassName("org.mariadb.jdbc.Driver"); + this.dataSource.setJdbcUrl("jdbc:mariadb://" + this.config.settings.host + ":" + this.config.settings.port + "/" + this.config.settings.databaseName); + } + + case H2 -> { + this.dataSource.setDriverClassName("org.h2.Driver"); + this.dataSource.setJdbcUrl("jdbc:h2:./" + this.dataFolder + "/database"); + } + + case SQLITE -> { + this.dataSource.setDriverClassName("org.sqlite.JDBC"); + this.dataSource.setJdbcUrl("jdbc:sqlite:" + this.dataFolder + "/database.db"); + } + + case POSTGRESQL -> { + this.dataSource.setDriverClassName("org.postgresql.Driver"); + this.dataSource.setJdbcUrl("jdbc:postgresql://" + this.config.settings.host + ":" + this.config.settings.port + "/"); + } + + default -> throw new IllegalStateException("Unexpected value: SQL type '" + databaseType + "' not found"); + } + + + this.connectionSource = new DataSourceConnectionSource(this.dataSource, this.dataSource.getJdbcUrl()); + + this.logger.info("Connected to database " + databaseType.toString().toLowerCase() + " in " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + "ms"); + } + + public void disconnect() { + try { + this.dataSource.close(); + this.connectionSource.close(); + } + catch (Exception exception) { + exception.printStackTrace(); + } + } + + @SuppressWarnings("unchecked") + public Dao getDao(Class type) { + try { + Dao dao = this.cachedDao.get(type); + + if (dao == null) { + dao = DaoManager.createDao(this.connectionSource, type); + this.cachedDao.put(type, dao); + } + + return (Dao) dao; + } + catch (SQLException exception) { + throw new RuntimeException(exception); + } + } + + public ConnectionSource connectionSource() { + return this.connectionSource; + } + +} diff --git a/src/main/java/com/eternalcode/parcellockers/database/DatabaseType.java b/src/main/java/com/eternalcode/parcellockers/database/DatabaseType.java index 2e4c6a1b..def9aa77 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/DatabaseType.java +++ b/src/main/java/com/eternalcode/parcellockers/database/DatabaseType.java @@ -2,5 +2,8 @@ public enum DatabaseType { MYSQL, - SQLITE + SQLITE, + H2, + POSTGRESQL, + MARIADB } diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java new file mode 100644 index 00000000..89a7a608 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java @@ -0,0 +1,67 @@ +package com.eternalcode.parcellockers.database.persister; + +import com.eternalcode.parcellockers.shared.Position; +import com.j256.ormlite.field.FieldType; +import com.j256.ormlite.field.SqlType; +import com.j256.ormlite.field.types.BaseDataType; +import com.j256.ormlite.support.DatabaseResults; + +import java.sql.SQLException; + +public class PositionPersister extends BaseDataType { + + private static final PositionPersister instance = new PositionPersister(); + + private PositionPersister() { + super(SqlType.LONG_STRING, new Class[] { PositionPersister.class }); + } + + public static PositionPersister getInstance() { + return instance; + } + + @Override + public Object javaToSqlArg(FieldType fieldType, Object javaObject) { + if (javaObject == null) { + return null; + } + + Position pos = (Position) javaObject; + String worldName = "world"; + + if (!pos.isNoneWorld()) { + worldName = pos.world(); + } + + return worldName + "/" + pos.x() + "/" + pos.y() + "/" + pos.z(); + } + + @Override + public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int columnPos) throws SQLException { + return results.getString(columnPos); + } + + @Override + public Object parseDefaultString(FieldType fieldType, String defaultStr) { + return String.valueOf(defaultStr); + } + + @Override + public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) { + String s = (String) sqlArg; + + if (s == null) { + return null; + } + + String[] params = s.split("/"); + + return new Position( + Integer.parseInt(params[1]), + Integer.parseInt(params[2]), + Integer.parseInt(params[3]), + params[0] + ); + } + +} diff --git a/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java new file mode 100644 index 00000000..5a6941ca --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java @@ -0,0 +1,72 @@ +package com.eternalcode.parcellockers.database.wrapper; + +import com.eternalcode.commons.scheduler.Scheduler; +import com.eternalcode.parcellockers.database.DatabaseManager; +import com.j256.ormlite.dao.Dao; +import panda.std.function.ThrowingFunction; + +import java.sql.SQLException; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +public abstract class AbstractRepositoryOrmLite { + + protected final DatabaseManager databaseManager; + protected final Scheduler scheduler; + + protected AbstractRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + this.databaseManager = databaseManager; + this.scheduler = scheduler; + } + + protected CompletableFuture save(Class type, T warp) { + return this.action(type, dao -> dao.createOrUpdate(warp)); + } + + protected CompletableFuture saveIfNotExist(Class type, T warp) { + return this.action(type, dao -> dao.createIfNotExists(warp)); + } + + protected CompletableFuture select(Class type, ID id) { + return this.action(type, dao -> dao.queryForId(id)); + } + + protected CompletableFuture> selectSafe(Class type, ID id) { + return this.action(type, dao -> Optional.ofNullable(dao.queryForId(id))); + } + + protected CompletableFuture delete(Class type, T warp) { + return this.action(type, dao -> dao.delete(warp)); + } + + protected CompletableFuture deleteAll(Class type) { + return this.action(type, dao -> dao.deleteBuilder().delete()); + } + + protected CompletableFuture deleteById(Class type, ID id) { + return this.action(type, dao -> dao.deleteById(id)); + } + + protected CompletableFuture> selectAll(Class type) { + return this.action(type, Dao::queryForAll); + } + + protected CompletableFuture action(Class type, ThrowingFunction, R, SQLException> action) { + CompletableFuture completableFuture = new CompletableFuture<>(); + + this.scheduler.runAsync(() -> { + Dao dao = this.databaseManager.getDao(type); + + try { + completableFuture.complete(action.apply(dao)); + } + catch (Throwable throwable) { + completableFuture.completeExceptionally(throwable); + } + }); + + return completableFuture; + } + +} diff --git a/src/main/java/com/eternalcode/parcellockers/shared/Position.java b/src/main/java/com/eternalcode/parcellockers/shared/Position.java index 3a3792b3..98b5fe21 100644 --- a/src/main/java/com/eternalcode/parcellockers/shared/Position.java +++ b/src/main/java/com/eternalcode/parcellockers/shared/Position.java @@ -55,7 +55,7 @@ public static boolean isWithin(Position a, Position b, int radius) { } public boolean isNoneWorld() { - return this.world.equals(NONE_WORLD); + return this.world.equals(NONE_WORLD) || this.world.isEmpty(); } @Override From 0810f481a2e2a3f54c85177d62e4c86e353e3d2b Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 29 Oct 2024 19:59:24 +0100 Subject: [PATCH 02/43] Add ParcelWrapper class, add ORMLite repository implementation --- .../parcellockers/ParcelLockers.java | 28 ++++- .../parcel/repository/ParcelRepository.java | 6 +- .../repository/ParcelRepositoryOrmLite.java | 109 ++++++++++++++++++ .../parcel/repository/ParcelWrapper.java | 55 +++++++++ 4 files changed, 189 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java create mode 100644 src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index ff9a8e8e..8cfa4c51 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -2,13 +2,15 @@ import com.eternalcode.commons.adventure.AdventureLegacyColorPostProcessor; import com.eternalcode.commons.adventure.AdventureLegacyColorPreProcessor; +import com.eternalcode.commons.bukkit.scheduler.BukkitSchedulerImpl; +import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.command.handler.InvalidUsageImpl; import com.eternalcode.parcellockers.command.handler.PermissionMessage; import com.eternalcode.parcellockers.configuration.ConfigurationManager; import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; import com.eternalcode.parcellockers.content.repository.ParcelContentRepository; import com.eternalcode.parcellockers.content.repository.ParcelContentRepositoryImpl; -import com.eternalcode.parcellockers.database.DataSourceFactory; +import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.gui.implementation.locker.LockerMainGUI; import com.eternalcode.parcellockers.gui.implementation.remote.MainGUI; import com.eternalcode.parcellockers.gui.implementation.remote.ParcelListGUI; @@ -26,7 +28,7 @@ import com.eternalcode.parcellockers.parcel.command.argument.ParcelArgument; import com.eternalcode.parcellockers.parcel.command.argument.ParcelLockerArgument; import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; -import com.eternalcode.parcellockers.parcel.repository.ParcelRepositoryImpl; +import com.eternalcode.parcellockers.parcel.repository.ParcelRepositoryOrmLite; import com.eternalcode.parcellockers.updater.UpdaterService; import com.eternalcode.parcellockers.user.LoadUserController; import com.eternalcode.parcellockers.user.PrepareUserController; @@ -34,7 +36,6 @@ import com.eternalcode.parcellockers.user.UserRepository; import com.eternalcode.parcellockers.user.UserRepositoryImpl; import com.google.common.base.Stopwatch; -import com.zaxxer.hikari.HikariDataSource; import dev.rollczi.litecommands.LiteCommands; import dev.rollczi.litecommands.adventure.LiteAdventureExtension; import dev.rollczi.litecommands.annotations.LiteCommandsAnnotations; @@ -54,6 +55,7 @@ import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; +import java.sql.SQLException; import java.time.Duration; import java.util.Arrays; import java.util.concurrent.TimeUnit; @@ -71,6 +73,8 @@ public final class ParcelLockers extends JavaPlugin { private Economy economy; + private DatabaseManager databaseManager; + @Override public void onEnable() { Stopwatch started = Stopwatch.createStarted(); @@ -87,6 +91,7 @@ public void onEnable() { ConfigurationManager configManager = new ConfigurationManager(this.getDataFolder()); PluginConfiguration config = configManager.load(new PluginConfiguration()); Server server = this.getServer(); + Scheduler scheduler = new BukkitSchedulerImpl(this); if (config.settings.enableSentry) { Sentry.init(options -> { @@ -101,7 +106,18 @@ public void onEnable() { }); } - HikariDataSource dataSource = DataSourceFactory.buildHikariDataSource(config, this.getDataFolder()); + //HikariDataSource dataSource = DataSourceFactory.buildHikariDataSource(config, this.getDataFolder()); + + DatabaseManager databaseManager = new DatabaseManager(config, this.getLogger(), this.getDataFolder()); + + try { + databaseManager.connect(); + } + catch (SQLException exception) { + this.getLogger().severe("Could not connect to database! Some functions may not work properly!"); + throw new RuntimeException(exception); + } + this.databaseManager = databaseManager; this.skullAPI = LiteSkullFactory.builder() .cacheExpireAfterWrite(Duration.ofMinutes(45L)) @@ -113,7 +129,7 @@ public void onEnable() { lockerRepository.updateCaches(); ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryImpl(dataSource); - ParcelRepository parcelRepository = new ParcelRepositoryImpl(dataSource); + ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager, scheduler); ParcelManager parcelManager = new ParcelManager(config, announcer, parcelRepository); @@ -163,6 +179,8 @@ public void onEnable() { @Override public void onDisable() { + this.databaseManager.disconnect(); + if (this.liteCommands != null) { this.liteCommands.unregister(); } diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java index 915db449..1a382ec4 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java @@ -13,17 +13,15 @@ public interface ParcelRepository { CompletableFuture save(Parcel parcel); - CompletableFuture update(Parcel parcel); - CompletableFuture> findByUUID(UUID uuid); CompletableFuture>> findBySender(UUID sender); CompletableFuture>> findByReceiver(UUID receiver); - CompletableFuture remove(Parcel parcel); + CompletableFuture remove(Parcel parcel); - CompletableFuture remove(UUID uuid); + CompletableFuture remove(UUID uuid); CompletableFuture findPage(Page page); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java new file mode 100644 index 00000000..5c4e1539 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -0,0 +1,109 @@ +package com.eternalcode.parcellockers.parcel.repository; + +import com.eternalcode.commons.scheduler.Scheduler; +import com.eternalcode.parcellockers.database.DatabaseManager; +import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; +import com.eternalcode.parcellockers.parcel.Parcel; +import com.eternalcode.parcellockers.shared.Page; +import com.j256.ormlite.table.TableUtils; +import io.sentry.Sentry; + +import java.sql.SQLException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class ParcelRepositoryOrmLite extends AbstractRepositoryOrmLite implements ParcelRepository { + + private static final String RECEIVER_COLUMN = "receiver"; + private static final String SENDER_COLUMN = "sender"; + + private final Map cache = new HashMap<>(); + + public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); + + try { + TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ParcelWrapper.class); + } catch (SQLException ex) { + Sentry.captureException(ex); + ex.printStackTrace(); + } + } + + @Override + public CompletableFuture save(Parcel parcel) { + return this.save(ParcelWrapper.class, ParcelWrapper.from(parcel)).thenApply(dao -> null); + } + + @Override + public CompletableFuture> findByUUID(UUID uuid) { + return this.selectSafe(ParcelWrapper.class, uuid).thenApply(optional -> optional.map(ParcelWrapper::toParcel)); + } + + @Override + public CompletableFuture>> findBySender(UUID sender) { + return this.action(ParcelWrapper.class, dao -> Optional.of(dao.queryForEq(SENDER_COLUMN, sender) + .stream() + .map(ParcelWrapper::toParcel) + .toList())); + } + + @Override + public CompletableFuture>> findByReceiver(UUID receiver) { + return this.action(ParcelWrapper.class, dao -> Optional.of(dao.queryForEq(RECEIVER_COLUMN, receiver) + .stream() + .map(ParcelWrapper::toParcel) + .toList())); + } + + @Override + public CompletableFuture remove(Parcel parcel) { + return this.delete(ParcelWrapper.class, ParcelWrapper.from(parcel)); + } + + @Override + public CompletableFuture remove(UUID uuid) { + return this.deleteById(ParcelWrapper.class, uuid); + } + + @Override + public CompletableFuture findPage(Page page) { + return this.action(ParcelWrapper.class, dao -> { + List parcels = dao.queryBuilder() + .limit((long) page.getLimit() + 1) + .offset((long) page.getOffset()) + .query() + .stream().map(ParcelWrapper::toParcel) + .toList(); + + boolean hasNext = parcels.size() > page.getLimit(); + if (hasNext) { + parcels.remove(parcels.size() - 1); + } + return new ParcelPageResult(parcels, hasNext); + }); + } + + @Override + public Map cache() { + return Collections.unmodifiableMap(this.cache); + } + + private void addToCache(Parcel parcel) { + this.cache.put(parcel.uuid(), parcel); + } + + private void removeFromCache(UUID uuid) { + this.cache.remove(uuid); + } + + @Override + public Optional findParcel(UUID uuid) { + return Optional.of(this.cache.get(uuid)); + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java new file mode 100644 index 00000000..ce30a682 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java @@ -0,0 +1,55 @@ +package com.eternalcode.parcellockers.parcel.repository; + +import com.eternalcode.parcellockers.parcel.Parcel; +import com.eternalcode.parcellockers.parcel.ParcelSize; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import java.util.Set; +import java.util.UUID; + +@DatabaseTable(tableName = "parcels") +class ParcelWrapper { + + @DatabaseField(id = true, columnName = "uuid") + private UUID uuid; + @DatabaseField(columnName = "sender") + private UUID sender; + @DatabaseField(columnName = "name") + private String name; + @DatabaseField(columnName = "description") + private String description; + @DatabaseField(columnName = "priority") + private boolean priority; + @DatabaseField(columnName = "receiver") + private UUID receiver; + @DatabaseField(columnName = "size") + private ParcelSize size; + @DatabaseField(columnName = "entryLocker") + private UUID entryLocker; + @DatabaseField(columnName = "destinationLocker") + private UUID destinationLocker; + + ParcelWrapper() { + } + + ParcelWrapper(UUID uuid, UUID sender, String name, String description, boolean priority, UUID receiver, ParcelSize size, UUID entryLocker, UUID destinationLocker) { + this.uuid = uuid; + this.sender = sender; + this.name = name; + this.description = description; + this.priority = priority; + this.receiver = receiver; + this.size = size; + this.entryLocker = entryLocker; + this.destinationLocker = destinationLocker; + } + + static ParcelWrapper from(Parcel parcel) { + return new ParcelWrapper(parcel.uuid(), parcel.sender(), parcel.name(), parcel.description(), parcel.priority(), parcel.receiver(), parcel.size(), parcel.entryLocker(), parcel.destinationLocker()); + } + + Parcel toParcel() { + return new Parcel(this.uuid, this.sender, this.name, this.description, this.priority, Set.of(this.sender), this.receiver, this.size, this.entryLocker, this.destinationLocker); + } +} From 57bcd6196db1bbaf215e876e3046fc65cc2bd4c9 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:18:43 +0100 Subject: [PATCH 03/43] Fix immutable list modification, apply codestyle changes --- .../parcel/repository/ParcelRepositoryOrmLite.java | 3 ++- .../parcellockers/parcel/repository/ParcelWrapper.java | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index 5c4e1539..26f2bae7 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -16,6 +16,7 @@ import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; public class ParcelRepositoryOrmLite extends AbstractRepositoryOrmLite implements ParcelRepository { @@ -79,7 +80,7 @@ public CompletableFuture findPage(Page page) { .offset((long) page.getOffset()) .query() .stream().map(ParcelWrapper::toParcel) - .toList(); + .collect(Collectors.toList()); boolean hasNext = parcels.size() > page.getLimit(); if (hasNext) { diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java index ce30a682..531a0735 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java @@ -13,20 +13,28 @@ class ParcelWrapper { @DatabaseField(id = true, columnName = "uuid") private UUID uuid; + @DatabaseField(columnName = "sender") private UUID sender; + @DatabaseField(columnName = "name") private String name; + @DatabaseField(columnName = "description") private String description; + @DatabaseField(columnName = "priority") private boolean priority; + @DatabaseField(columnName = "receiver") private UUID receiver; + @DatabaseField(columnName = "size") private ParcelSize size; + @DatabaseField(columnName = "entryLocker") private UUID entryLocker; + @DatabaseField(columnName = "destinationLocker") private UUID destinationLocker; From ed59bd614ea3c6d534d9b085d14df16a5b1e5a72 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:26:19 +0100 Subject: [PATCH 04/43] Implement Locker ORMLite repository --- .../parcellockers/ParcelLockers.java | 4 +- .../locker/repository/LockerRepository.java | 8 +- .../repository/LockerRepositoryImpl.java | 2 +- .../repository/LockerRepositoryOrmLite.java | 118 ++++++++++++++++++ .../locker/repository/LockerWrapper.java | 39 ++++++ .../repository/ParcelRepositoryImpl.java | 4 +- 6 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java create mode 100644 src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index 8cfa4c51..a6ac86c1 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -20,7 +20,7 @@ import com.eternalcode.parcellockers.locker.controller.LockerBreakController; import com.eternalcode.parcellockers.locker.controller.LockerInteractionController; import com.eternalcode.parcellockers.locker.controller.LockerPlaceController; -import com.eternalcode.parcellockers.locker.repository.LockerRepositoryImpl; +import com.eternalcode.parcellockers.locker.repository.LockerRepositoryOrmLite; import com.eternalcode.parcellockers.notification.NotificationAnnouncer; import com.eternalcode.parcellockers.parcel.Parcel; import com.eternalcode.parcellockers.parcel.ParcelManager; @@ -125,7 +125,7 @@ public void onEnable() { .threadPool(20) .build(); - LockerRepositoryImpl lockerRepository = new LockerRepositoryImpl(dataSource); + LockerRepositoryOrmLite lockerRepository = new LockerRepositoryOrmLite(databaseManager, scheduler); lockerRepository.updateCaches(); ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryImpl(dataSource); diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java index 93a52f83..0d28d782 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java @@ -14,21 +14,19 @@ public interface LockerRepository { CompletableFuture save(Locker locker); - CompletableFuture update(Locker locker); - CompletableFuture> findAll(); CompletableFuture> findByUUID(UUID uuid); CompletableFuture> findByPosition(Position position); - CompletableFuture remove(UUID uuid); + CompletableFuture remove(UUID uuid); - CompletableFuture remove(Locker locker); + CompletableFuture remove(Locker locker); CompletableFuture findPage(Page page); - Optional findLocker(UUID uuid); + Optional getFromCache(UUID uuid); Map cache(); diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java index 686351a3..8aed857a 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java @@ -129,7 +129,7 @@ private List extractLockers(PreparedStatement statement) throws SQLExcep } @Override - public Optional findLocker(UUID uuid) { + public Optional getFromCache(UUID uuid) { if (this.isInCache(uuid)) { return Optional.ofNullable(this.cache.get(uuid)); } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java new file mode 100644 index 00000000..89477d8b --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -0,0 +1,118 @@ +package com.eternalcode.parcellockers.locker.repository; + +import com.eternalcode.commons.scheduler.Scheduler; +import com.eternalcode.parcellockers.database.DatabaseManager; +import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; +import com.eternalcode.parcellockers.locker.Locker; +import com.eternalcode.parcellockers.shared.Page; +import com.eternalcode.parcellockers.shared.Position; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +public class LockerRepositoryOrmLite extends AbstractRepositoryOrmLite implements LockerRepository { + + private final Map cache = new HashMap<>(); + private final Map positionCache = new HashMap<>(); + + public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); + } + + @Override + public CompletableFuture save(Locker locker) { + return this.save(LockerWrapper.class, LockerWrapper.from(locker)).thenApply(dao -> null); + } + + @Override + public CompletableFuture> findAll() { + return this.selectAll(LockerWrapper.class).thenApply(lockers -> lockers.stream() + .map(LockerWrapper::toLocker) + .collect(Collectors.toList())); + } + + @Override + public CompletableFuture> findByUUID(UUID uuid) { + return this.selectSafe(LockerWrapper.class, uuid).thenApply(optional -> optional.map(LockerWrapper::toLocker)); + } + + @Override + public CompletableFuture> findByPosition(Position position) { + // We have to assume that there is only one locker per position + return this.action(LockerWrapper.class, dao -> { + List lockers = dao.queryForEq("position", position); + return lockers.isEmpty() ? Optional.empty() : Optional.of(lockers.get(0).toLocker()); + }); + } + + @Override + public CompletableFuture remove(UUID uuid) { + return this.deleteById(LockerWrapper.class, uuid); + } + + @Override + public CompletableFuture remove(Locker locker) { + return this.action(LockerWrapper.class, dao -> dao.delete(LockerWrapper.from(locker))); + } + + @Override + public CompletableFuture findPage(Page page) { + return this.action(LockerWrapper.class, dao -> { + List lockers = dao.queryBuilder() + .offset((long) page.getOffset()) + .limit((long) page.getLimit() + 1) + .query() + .stream().map(LockerWrapper::toLocker) + .collect(Collectors.toList()); + + boolean hasNext = lockers.size() > page.getLimit(); + if (hasNext) { + lockers.remove(lockers.size() - 1); + } + + return new LockerPageResult(lockers, hasNext); + }); + } + + @Override + public Optional getFromCache(UUID uuid) { + return Optional.ofNullable(this.cache.get(uuid)); + } + + @Override + public Map cache() { + return Collections.unmodifiableMap(this.cache); + } + + @Override + public Map positionCache() { + return Collections.unmodifiableMap(this.positionCache); + } + + @Override + public boolean isInCache(Position position) { + return this.positionCache.containsKey(position); + } + + @Override + public boolean isInCache(UUID uuid) { + return this.cache.containsKey(uuid); + } + + public void updateCaches() { + this.cache.clear(); + this.positionCache.clear(); + this.findAll().thenAccept(lockers -> lockers.forEach(this::addToCache)); + } + + private void addToCache(Locker locker) { + this.cache.put(locker.uuid(), locker); + this.positionCache.put(locker.position(), locker.uuid()); + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java new file mode 100644 index 00000000..af9d476c --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java @@ -0,0 +1,39 @@ +package com.eternalcode.parcellockers.locker.repository; + +import com.eternalcode.parcellockers.database.persister.PositionPersister; +import com.eternalcode.parcellockers.locker.Locker; +import com.eternalcode.parcellockers.shared.Position; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import java.util.UUID; + +@DatabaseTable(tableName = "lockers") +class LockerWrapper { + + @DatabaseField(id = true, columnName = "uuid") + private UUID uuid; + + @DatabaseField(columnName = "description") + private String description; + + @DatabaseField(columnName = "position", persisterClass = PositionPersister.class) + private Position position; + + LockerWrapper() { + } + + LockerWrapper(UUID uuid, String description, Position position) { + this.uuid = uuid; + this.description = description; + this.position = position; + } + + static LockerWrapper from(Locker locker) { + return new LockerWrapper(locker.uuid(), locker.description(), locker.position()); + } + + Locker toLocker() { + return new Locker(this.uuid, this.description, this.position); + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java index d863432e..7ba66fab 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java @@ -122,12 +122,12 @@ public CompletableFuture>> findByReceiver(UUID receiver) { } @Override - public CompletableFuture remove(Parcel parcel) { + public CompletableFuture remove(Parcel parcel) { return this.remove(parcel.uuid()); } @Override - public CompletableFuture remove(UUID uuid) { + public CompletableFuture remove(UUID uuid) { return this.supplyExecute("DELETE FROM `parcels` WHERE `uuid` = ?", statement -> { statement.setString(1, uuid.toString()); statement.execute(); From fbeb6b300fd29106f664015fbff726900dc4e2d9 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 30 Oct 2024 20:17:43 +0100 Subject: [PATCH 05/43] Add ItemStorage ORMLite repository implementation --- .../parcellockers/ParcelLockers.java | 4 +- .../persister/ItemStackPersister.java | 79 +++++++++++++++++++ .../database/persister/PositionPersister.java | 2 + .../repository/ItemStorageRepository.java | 5 +- .../ItemStorageRepositoryOrmLite.java | 42 ++++++++++ .../repository/ItemStorageWrapper.java | 37 +++++++++ .../repository/LockerRepositoryOrmLite.java | 10 +++ 7 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java create mode 100644 src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java create mode 100644 src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageWrapper.java diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index a6ac86c1..bb7df56b 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -15,7 +15,7 @@ import com.eternalcode.parcellockers.gui.implementation.remote.MainGUI; import com.eternalcode.parcellockers.gui.implementation.remote.ParcelListGUI; import com.eternalcode.parcellockers.itemstorage.repository.ItemStorageRepository; -import com.eternalcode.parcellockers.itemstorage.repository.ItemStorageRepositoryImpl; +import com.eternalcode.parcellockers.itemstorage.repository.ItemStorageRepositoryOrmLite; import com.eternalcode.parcellockers.locker.Locker; import com.eternalcode.parcellockers.locker.controller.LockerBreakController; import com.eternalcode.parcellockers.locker.controller.LockerInteractionController; @@ -127,7 +127,7 @@ public void onEnable() { LockerRepositoryOrmLite lockerRepository = new LockerRepositoryOrmLite(databaseManager, scheduler); lockerRepository.updateCaches(); - ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryImpl(dataSource); + ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryOrmLite(databaseManager, scheduler); ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager, scheduler); diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java new file mode 100644 index 00000000..ed7643ba --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java @@ -0,0 +1,79 @@ +package com.eternalcode.parcellockers.database.persister; + +import com.eternalcode.parcellockers.exception.ParcelLockersException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.j256.ormlite.field.FieldType; +import com.j256.ormlite.field.SqlType; +import com.j256.ormlite.field.types.BaseDataType; +import com.j256.ormlite.support.DatabaseResults; +import de.eldoria.jacksonbukkit.JacksonPaper; +import io.sentry.Sentry; +import org.bukkit.inventory.ItemStack; + +import java.sql.SQLException; +import java.util.List; + +public class ItemStackPersister extends BaseDataType { + + private static final ItemStackPersister instance = new ItemStackPersister(); + private static final ObjectMapper JSON = JsonMapper.builder() + .addModule(JacksonPaper.builder() + .useLegacyItemStackSerialization() + .build() + ) + .build(); + + private ItemStackPersister() { + super(SqlType.LONG_STRING, new Class[] { ItemStackPersister.class }); + } + + public static ItemStackPersister getInstance() { + return instance; + } + + @Override + public Object javaToSqlArg(FieldType fieldType, Object javaObject) { + if (javaObject == null) { + return null; + } + + List stacks = (List) javaObject; + + try { + return JSON.writeValueAsString(stacks); + } + catch (JsonProcessingException e) { + Sentry.captureException(e); + throw new ParcelLockersException("Failed to serialize itemstacks", e); + } + } + + @Override + public Object parseDefaultString(FieldType fieldType, String defaultString) { + return String.valueOf(defaultString); + } + + @Override + public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int columnPos) throws SQLException { + return results.getString(columnPos); + } + + @Override + public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) { + String string = (String) sqlArg; + + if (string == null) { + return null; + } + + try { + return JSON.readValue(string, JSON.getTypeFactory().constructCollectionType(List.class, ItemStack.class)); + } + catch (JsonProcessingException exception) { + Sentry.captureException(exception); + throw new ParcelLockersException("Failed to deserialize itemstacks", exception); + } + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java index 89a7a608..869a5d37 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java @@ -36,6 +36,8 @@ public Object javaToSqlArg(FieldType fieldType, Object javaObject) { return worldName + "/" + pos.x() + "/" + pos.y() + "/" + pos.z(); } + + @Override public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int columnPos) throws SQLException { return results.getString(columnPos); diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepository.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepository.java index 3bab2cb5..0b1b5233 100644 --- a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepository.java @@ -12,8 +12,5 @@ public interface ItemStorageRepository { CompletableFuture> find(UUID uuid); - CompletableFuture remove(UUID uuid); - - CompletableFuture update(ItemStorage itemStorage); - + CompletableFuture remove(UUID uuid); } diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java new file mode 100644 index 00000000..4e5a4ff2 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java @@ -0,0 +1,42 @@ +package com.eternalcode.parcellockers.itemstorage.repository; + +import com.eternalcode.commons.scheduler.Scheduler; +import com.eternalcode.parcellockers.database.DatabaseManager; +import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; +import com.eternalcode.parcellockers.itemstorage.ItemStorage; +import com.j256.ormlite.table.TableUtils; +import io.sentry.Sentry; + +import java.sql.SQLException; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class ItemStorageRepositoryOrmLite extends AbstractRepositoryOrmLite implements ItemStorageRepository { + + public ItemStorageRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); + + try { + TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ItemStorageWrapper.class); + } catch (SQLException ex) { + Sentry.captureException(ex); + ex.printStackTrace(); + } + } + + @Override + public CompletableFuture save(ItemStorage itemStorage) { + return this.save(ItemStorageWrapper.class, ItemStorageWrapper.from(itemStorage.owner(), itemStorage.items())).thenApply(dao -> null); + } + + @Override + public CompletableFuture> find(UUID uuid) { + return this.selectSafe(ItemStorageWrapper.class, uuid).thenApply(optional -> optional.map(ItemStorageWrapper::toItemStorage)); + } + + @Override + public CompletableFuture remove(UUID uuid) { + return this.deleteById(ItemStorageWrapper.class, uuid); + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageWrapper.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageWrapper.java new file mode 100644 index 00000000..84cdad91 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageWrapper.java @@ -0,0 +1,37 @@ +package com.eternalcode.parcellockers.itemstorage.repository; + +import com.eternalcode.parcellockers.database.persister.ItemStackPersister; +import com.eternalcode.parcellockers.itemstorage.ItemStorage; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; +import org.bukkit.inventory.ItemStack; + +import java.util.List; +import java.util.UUID; + +@DatabaseTable(tableName = "item_storage") +class ItemStorageWrapper { + + @DatabaseField(id = true) + private UUID uuid; + + @DatabaseField(persisterClass = ItemStackPersister.class) + private List items; + + ItemStorageWrapper() { + } + + ItemStorageWrapper(UUID uuid, List items) { + this.uuid = uuid; + this.items = items; + } + + public static ItemStorageWrapper from(UUID uuid, List items) { + return new ItemStorageWrapper(uuid, items); + } + + ItemStorage toItemStorage() { + return new ItemStorage(this.uuid, this.items); + } + +} diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java index 89477d8b..fe28beb2 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -6,7 +6,10 @@ import com.eternalcode.parcellockers.locker.Locker; import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.shared.Position; +import com.j256.ormlite.table.TableUtils; +import io.sentry.Sentry; +import java.sql.SQLException; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -23,6 +26,13 @@ public class LockerRepositoryOrmLite extends AbstractRepositoryOrmLite implement public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { super(databaseManager, scheduler); + + try { + TableUtils.createTableIfNotExists(databaseManager.connectionSource(), LockerWrapper.class); + } catch (SQLException ex) { + Sentry.captureException(ex); + ex.printStackTrace(); + } } @Override From 69288e0094a0c38c522dff07fab97f6f21074cc1 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 30 Oct 2024 20:47:45 +0100 Subject: [PATCH 06/43] Add User ORMLite implementation --- .../parcellockers/ParcelLockers.java | 6 +- .../implementation/locker/LockerMainGUI.java | 2 +- .../locker/ParcelItemStorageGUI.java | 2 +- .../locker/ParcelSendingGUI.java | 2 +- .../locker/ReceiverSelectionGui.java | 5 +- .../repository/ItemStorageRepositoryImpl.java | 68 ------ .../repository/LockerRepositoryImpl.java | 203 ---------------- .../repository/ParcelRepositoryImpl.java | 227 ------------------ .../parcellockers/user/UserManager.java | 2 + .../parcellockers/user/UserPageResult.java | 7 - .../user/UserRepositoryImpl.java | 137 ----------- .../user/repository/UserPageResult.java | 9 + .../user/{ => repository}/UserRepository.java | 3 +- .../repository/UserRepositoryOrmLite.java | 76 ++++++ .../user/repository/UserWrapper.java | 37 +++ .../ParcelDatabaseServiceIntegrationTest.java | 1 - 16 files changed, 134 insertions(+), 653 deletions(-) delete mode 100644 src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryImpl.java delete mode 100644 src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java delete mode 100644 src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java delete mode 100644 src/main/java/com/eternalcode/parcellockers/user/UserPageResult.java delete mode 100644 src/main/java/com/eternalcode/parcellockers/user/UserRepositoryImpl.java create mode 100644 src/main/java/com/eternalcode/parcellockers/user/repository/UserPageResult.java rename src/main/java/com/eternalcode/parcellockers/user/{ => repository}/UserRepository.java (82%) create mode 100644 src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java create mode 100644 src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index bb7df56b..3ba6ccf0 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -33,8 +33,8 @@ import com.eternalcode.parcellockers.user.LoadUserController; import com.eternalcode.parcellockers.user.PrepareUserController; import com.eternalcode.parcellockers.user.UserManager; -import com.eternalcode.parcellockers.user.UserRepository; -import com.eternalcode.parcellockers.user.UserRepositoryImpl; +import com.eternalcode.parcellockers.user.repository.UserRepository; +import com.eternalcode.parcellockers.user.repository.UserRepositoryOrmLite; import com.google.common.base.Stopwatch; import dev.rollczi.litecommands.LiteCommands; import dev.rollczi.litecommands.adventure.LiteAdventureExtension; @@ -133,7 +133,7 @@ public void onEnable() { ParcelManager parcelManager = new ParcelManager(config, announcer, parcelRepository); - UserRepository userRepository = new UserRepositoryImpl(dataSource); + UserRepository userRepository = new UserRepositoryOrmLite(databaseManager, scheduler); UserManager userManager = new UserManager(userRepository); ParcelContentRepository parcelContentRepository = new ParcelContentRepositoryImpl(dataSource); diff --git a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/LockerMainGUI.java b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/LockerMainGUI.java index 1782db79..44c7f305 100644 --- a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/LockerMainGUI.java +++ b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/LockerMainGUI.java @@ -7,7 +7,7 @@ import com.eternalcode.parcellockers.locker.repository.LockerRepository; import com.eternalcode.parcellockers.notification.NotificationAnnouncer; import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; -import com.eternalcode.parcellockers.user.UserRepository; +import com.eternalcode.parcellockers.user.repository.UserRepository; import dev.rollczi.liteskullapi.SkullAPI; import dev.triumphteam.gui.guis.Gui; import dev.triumphteam.gui.guis.GuiItem; diff --git a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelItemStorageGUI.java b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelItemStorageGUI.java index ff992869..0794bb70 100644 --- a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelItemStorageGUI.java +++ b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelItemStorageGUI.java @@ -9,7 +9,7 @@ import com.eternalcode.parcellockers.parcel.ParcelSize; import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; import com.eternalcode.parcellockers.shared.ExceptionHandler; -import com.eternalcode.parcellockers.user.UserRepository; +import com.eternalcode.parcellockers.user.repository.UserRepository; import com.eternalcode.parcellockers.util.InventoryUtil; import dev.rollczi.liteskullapi.SkullAPI; import dev.triumphteam.gui.guis.Gui; diff --git a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelSendingGUI.java b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelSendingGUI.java index 7001f0ce..8c7a567c 100644 --- a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelSendingGUI.java +++ b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelSendingGUI.java @@ -13,7 +13,7 @@ import com.eternalcode.parcellockers.parcel.ParcelSize; import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; import com.eternalcode.parcellockers.shared.ExceptionHandler; -import com.eternalcode.parcellockers.user.UserRepository; +import com.eternalcode.parcellockers.user.repository.UserRepository; import de.rapha149.signgui.SignGUI; import de.rapha149.signgui.SignGUIAction; import dev.rollczi.liteskullapi.SkullAPI; diff --git a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ReceiverSelectionGui.java b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ReceiverSelectionGui.java index 3eb6f836..179ff28a 100644 --- a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ReceiverSelectionGui.java +++ b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ReceiverSelectionGui.java @@ -6,8 +6,8 @@ import com.eternalcode.parcellockers.shared.ExceptionHandler; import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.user.User; -import com.eternalcode.parcellockers.user.UserPageResult; -import com.eternalcode.parcellockers.user.UserRepository; +import com.eternalcode.parcellockers.user.repository.UserPageResult; +import com.eternalcode.parcellockers.user.repository.UserRepository; import com.spotify.futures.CompletableFutures; import dev.rollczi.liteskullapi.SkullAPI; import dev.rollczi.liteskullapi.SkullData; @@ -15,7 +15,6 @@ import dev.triumphteam.gui.guis.Gui; import dev.triumphteam.gui.guis.GuiItem; import dev.triumphteam.gui.guis.PaginatedGui; -import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryImpl.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryImpl.java deleted file mode 100644 index 9e104de9..00000000 --- a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.eternalcode.parcellockers.itemstorage.repository; - -import com.eternalcode.parcellockers.database.AbstractDatabaseService; -import com.eternalcode.parcellockers.itemstorage.ItemStorage; -import com.eternalcode.parcellockers.util.ItemSerdesUtil; - -import javax.sql.DataSource; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -public class ItemStorageRepositoryImpl extends AbstractDatabaseService implements ItemStorageRepository { - - public ItemStorageRepositoryImpl(DataSource dataSource) { - super(dataSource); - - this.initTable(); - } - - private void initTable() { - this.executeSync("CREATE TABLE IF NOT EXISTS `item_storage`(`uuid` VARCHAR(36) NOT NULL, `items` BLOB NULL, PRIMARY KEY (uuid));", PreparedStatement::execute); - } - - @Override - public CompletableFuture save(ItemStorage itemStorage) { - return this.execute("INSERT INTO `item_storage`(`uuid`, `items`) VALUES (?, ?)", statement -> { - statement.setString(1, itemStorage.owner().toString()); - statement.setString(2, ItemSerdesUtil.serializeItems(itemStorage.items())); - statement.execute(); - }); - } - - @Override - public CompletableFuture update(ItemStorage itemStorage) { - return this.execute("UPDATE `item_storage` SET `items` = ? WHERE `uuid` = ?", statement -> { - statement.setString(1, ItemSerdesUtil.serializeItems(itemStorage.items())); - statement.setString(2, itemStorage.owner().toString()); - statement.execute(); - }); - } - - @Override - public CompletableFuture> find(UUID uuid) { - return this.supplyExecute("SELECT * FROM `item_storage` WHERE `uuid` = ?", statement -> { - statement.setString(1, uuid.toString()); - ResultSet resultSet = statement.executeQuery(); - if (!resultSet.next()) { - return Optional.empty(); - } - - return Optional.of( - new ItemStorage( - UUID.fromString(resultSet.getString("uuid")), - ItemSerdesUtil.deserializeItems(resultSet.getString("items")) - )); - }); - } - - @Override - public CompletableFuture remove(UUID uuid) { - return this.execute("DELETE FROM `item_storage` WHERE `uuid` = ?", statement -> { - statement.setString(1, uuid.toString()); - statement.execute(); - }); - } -} diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java deleted file mode 100644 index 8aed857a..00000000 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.eternalcode.parcellockers.locker.repository; - -import com.eternalcode.parcellockers.database.AbstractDatabaseService; -import com.eternalcode.parcellockers.locker.Locker; -import com.eternalcode.parcellockers.shared.Page; -import com.eternalcode.parcellockers.shared.Position; - -import javax.sql.DataSource; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; - -public class LockerRepositoryImpl extends AbstractDatabaseService implements LockerRepository { - - private final Map cache = new HashMap<>(); - private final Map positionCache = new HashMap<>(); - - public LockerRepositoryImpl(DataSource dataSource) { - super(dataSource); - - this.initTable(); - } - - private void initTable() { - this.executeSync("CREATE TABLE IF NOT EXISTS `lockers`(" + - "uuid VARCHAR(36) NOT NULL, " + - "description VARCHAR(64) NOT NULL, " + - "position VARCHAR(255) NOT NULL, " + - "PRIMARY KEY (uuid)" + - ");", PreparedStatement::execute); - } - - @Override - public CompletableFuture save(Locker locker) { - return this.execute("INSERT INTO `lockers`(`uuid`, `description`, `position`) VALUES (?, ?, ?) ", statement -> { - statement.setString(1, locker.uuid().toString()); - statement.setString(2, locker.description()); - statement.setString(3, locker.position().toString()); - statement.execute(); - - this.addToCache(locker); - }).orTimeout(5, TimeUnit.SECONDS); - } - - - @Override - public CompletableFuture update(Locker locker) { - return this.execute("UPDATE `lockers` SET `description` = ?, `position` = ? WHERE `uuid` = ?;", statement -> { - statement.setString(1, locker.description()); - statement.setString(2, locker.position().toString()); - statement.setString(3, locker.uuid().toString()); - statement.execute(); - }); - } - - @Override - public CompletableFuture> findAll() { - return this.supplyExecute("SELECT * FROM `lockers`;", this::extractLockers); - } - - - @Override - public CompletableFuture> findByUUID(UUID uuid) { - return this.findBy("uuid", uuid.toString()); - } - - @Override - public CompletableFuture> findByPosition(Position position) { - return this.findBy("position", position.toString()); - } - - @Override - public CompletableFuture remove(UUID uuid) { - return this.execute("DELETE FROM `lockers` WHERE `uuid` = ?;", statement -> { - statement.setString(1, uuid.toString()); - statement.execute(); - - this.removeFromCache(uuid); - }); - } - - @Override - public CompletableFuture remove(Locker locker) { - return this.remove(locker.uuid()); - } - - @Override - public CompletableFuture findPage(Page page) { - return this.supplyExecute("SELECT * FROM `lockers` LIMIT ? OFFSET ?;", statement -> { - statement.setInt(1, page.getLimit() + 1); - statement.setInt(2, page.getOffset()); - - List lockers = this.extractLockers(statement); - - boolean hasNext = lockers.size() > page.getLimit(); - if (hasNext) { - lockers.remove(lockers.size() - 1); - } - return new LockerPageResult(lockers, hasNext); - }); - } - - private List extractLockers(PreparedStatement statement) throws SQLException { - List list = new ArrayList<>(); - ResultSet rs = statement.executeQuery(); - - while (rs.next()) { - Locker locker = new Locker( - UUID.fromString(rs.getString("uuid")), - rs.getString("description"), - Position.parse(rs.getString("position")) - ); - - list.add(locker); - } - - list.forEach(this::addToCache); - - return list; - } - - @Override - public Optional getFromCache(UUID uuid) { - if (this.isInCache(uuid)) { - return Optional.ofNullable(this.cache.get(uuid)); - } - return this.findByUUID(uuid).orTimeout(2, TimeUnit.SECONDS).join(); - } - - private void addToCache(Locker locker) { - this.cache.put(locker.uuid(), locker); - this.positionCache.put(locker.position(), locker.uuid()); - } - - private void removeFromCache(UUID uuid) { - this.positionCache.remove(this.cache.get(uuid).position()); - this.cache.remove(uuid); - } - - @Override - public Map cache() { - return this.cache; - } - - @Override - public Map positionCache() { - return Collections.unmodifiableMap(this.positionCache); - } - - @Override - public boolean isInCache(Position position) { - return this.positionCache().containsKey(position); - } - - @Override - public boolean isInCache(UUID uuid) { - return this.cache.containsKey(uuid); - } - - public CompletableFuture updateCaches() { - return this.execute("SELECT * FROM `lockers` WHERE `position` IS NOT NULL;", statement -> { - ResultSet rs = statement.executeQuery(); - - this.positionCache.clear(); - this.cache.clear(); - - while (rs.next()) { - Position position = Position.parse(rs.getString("position")); - UUID uuid = UUID.fromString(rs.getString("uuid")); - - this.positionCache.put(position, uuid); - this.cache.put(uuid, new Locker(uuid, rs.getString("description"), position)); - } - }); - } - - private CompletableFuture> findBy(String column, String value) { - return this.supplyExecute("SELECT * FROM `lockers` WHERE `" + column + "` = ?;", statement -> { - statement.setString(1, value); - ResultSet rs = statement.executeQuery(); - if (rs.next()) { - Locker locker = new Locker( - UUID.fromString(rs.getString("uuid")), - rs.getString("description"), - Position.parse(rs.getString("position")) - ); - - this.addToCache(locker); - return Optional.of(locker); - } - return Optional.empty(); - }); - } -} diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java deleted file mode 100644 index 7ba66fab..00000000 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java +++ /dev/null @@ -1,227 +0,0 @@ -package com.eternalcode.parcellockers.parcel.repository; - -import com.eternalcode.parcellockers.database.AbstractDatabaseService; -import com.eternalcode.parcellockers.parcel.Parcel; -import com.eternalcode.parcellockers.parcel.ParcelSize; -import com.eternalcode.parcellockers.shared.Page; - -import javax.sql.DataSource; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -public class ParcelRepositoryImpl extends AbstractDatabaseService implements ParcelRepository { - - private final Map cache = new HashMap<>(); - - public ParcelRepositoryImpl(DataSource dataSource) { - super(dataSource); - - this.initTable(); - } - - private void initTable() { - this.executeSync("CREATE TABLE IF NOT EXISTS `parcels`(" + - "`uuid` VARCHAR(36) NOT NULL, " + - "`name` VARCHAR(24) NOT NULL, " + - "`description` VARCHAR(64), " + - "`priority` BOOLEAN NOT NULL, " + - "`receiver` VARCHAR(36) NOT NULL, " + - "`size` VARCHAR(10) NOT NULL, " + - "`entryLocker` VARCHAR(36) NOT NULL, " + - "`destinationLocker` VARCHAR(36) NOT NULL, " + - "`sender` VARCHAR(36) NOT NULL, " + - "PRIMARY KEY (uuid) " + - ");", PreparedStatement::execute); - } - - @Override - public CompletableFuture save(Parcel parcel) { - return this.execute("INSERT INTO `parcels`(uuid, " + - "`name`, " + - "`description`, " + - "`priority`, " + - "`receiver`, " + - "`size`, " + - "`entryLocker`, " + - "`destinationLocker`, " + - "`sender`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", statement -> { - statement.setString(1, parcel.uuid().toString()); - statement.setString(2, parcel.name()); - statement.setString(3, parcel.description()); - statement.setBoolean(4, parcel.priority()); - statement.setString(5, parcel.receiver().toString()); - statement.setString(6, parcel.size().name()); - statement.setString(7, parcel.entryLocker().toString()); - statement.setString(8, parcel.destinationLocker().toString()); - statement.setString(9, parcel.sender().toString()); - statement.execute(); - - this.addParcelToCache(parcel); - }); - } - - @Override - public CompletableFuture update(Parcel parcel) { - return this.execute("UPDATE `parcels` SET " + - "`name` = ?, " + - "`description` = ?, " + - "`priority` = ?, " + - "`receiver` = ?, " + - "`size` = ?, " + - "`entryLocker` = ?, " + - "`destinationLocker` = ?, " + - "`sender` = ? " + - "WHERE `uuid` = ?", statement -> { - statement.setString(1, parcel.name()); - statement.setString(2, parcel.description()); - statement.setBoolean(3, parcel.priority()); - statement.setString(4, parcel.receiver().toString()); - statement.setString(5, parcel.size().name()); - statement.setString(6, parcel.entryLocker().toString()); - statement.setString(7, parcel.destinationLocker().toString()); - statement.setString(8, parcel.sender().toString()); - statement.setString(9, parcel.uuid().toString()); - statement.execute(); - }); - } - - @Override - public CompletableFuture> findByUUID(UUID uuid) { - return this.supplyExecute("SELECT * FROM `parcels` WHERE `uuid` = ?", statement -> { - statement.setString(1, uuid.toString()); - ResultSet rs = statement.executeQuery(); - if (rs.next()) { - Parcel parcel = this.createParcel(rs); - - this.addParcelToCache(parcel); - - return Optional.of(parcel); - } - return Optional.empty(); - }); - } - - @Override - public CompletableFuture>> findBySender(UUID sender) { - return this.findByMultiple("sender", sender.toString()); - } - - @Override - public CompletableFuture>> findByReceiver(UUID receiver) { - return this.findByMultiple("receiver", receiver.toString()); - } - - @Override - public CompletableFuture remove(Parcel parcel) { - return this.remove(parcel.uuid()); - } - - @Override - public CompletableFuture remove(UUID uuid) { - return this.supplyExecute("DELETE FROM `parcels` WHERE `uuid` = ?", statement -> { - statement.setString(1, uuid.toString()); - statement.execute(); - - this.removeParcelFromCache(uuid); - return null; - }); - } - - @Override - public CompletableFuture findPage(Page page) { - return this.supplyExecute("SELECT * FROM `parcels` LIMIT ? OFFSET ?;", statement -> { - statement.setInt(1, page.getLimit() + 1); - statement.setInt(2, page.getOffset()); - ResultSet rs = statement.executeQuery(); - - List parcels = new ArrayList<>(); - while (rs.next()) { - Parcel parcel = this.createParcel(rs); - this.addParcelToCache(parcel); - parcels.add(parcel); - } - - boolean hasNext = parcels.size() > page.getLimit(); - if (hasNext) { - parcels.remove(parcels.size() - 1); - } - return new ParcelPageResult(parcels, hasNext); - }); - } - - private Parcel createParcel(ResultSet rs) throws SQLException { - return new Parcel( - UUID.fromString(rs.getString("uuid")), - UUID.fromString(rs.getString("sender")), - rs.getString("name"), - rs.getString("description"), - rs.getBoolean("priority"), - new HashSet<>(), - UUID.fromString(rs.getString("receiver")), - ParcelSize.valueOf(rs.getString("size")), - UUID.fromString(rs.getString("entryLocker")), - UUID.fromString(rs.getString("destinationLocker")) - ); - } - - private CompletableFuture> findBy(String column, String value) { - return this.supplyExecute("SELECT * FROM `parcels` WHERE `" + column + "` = ?;", statement -> { - statement.setString(1, value); - ResultSet rs = statement.executeQuery(); - if (rs.next()) { - Parcel parcel = this.createParcel(rs); - this.addParcelToCache(parcel); - return Optional.of(parcel); - } - return Optional.empty(); - }); - } - - private CompletableFuture>> findByMultiple(String column, String value) { - return this.supplyExecute("SELECT * FROM `parcels` WHERE `" + column + "` = ?;", statement -> { - statement.setString(1, value); - ResultSet rs = statement.executeQuery(); - List parcels = new ArrayList<>(); - - while (rs.next()) { - Parcel parcel = this.createParcel(rs); - this.addParcelToCache(parcel); - - parcels.add(parcel); - } - - if (!parcels.isEmpty()) { - return Optional.of(parcels); - } - - return Optional.empty(); - }); - } - - - public Optional findParcel(UUID uuid) { - return Optional.ofNullable(this.cache.get(uuid)); - } - - private void addParcelToCache(Parcel parcel) { - this.cache.put(parcel.uuid(), parcel); - } - - private void removeParcelFromCache(UUID uuid) { - this.cache.remove(uuid); - } - - public Map cache() { - return Collections.unmodifiableMap(this.cache); - } -} diff --git a/src/main/java/com/eternalcode/parcellockers/user/UserManager.java b/src/main/java/com/eternalcode/parcellockers/user/UserManager.java index 70dd2dfb..4f5a62d0 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/UserManager.java +++ b/src/main/java/com/eternalcode/parcellockers/user/UserManager.java @@ -1,5 +1,7 @@ package com.eternalcode.parcellockers.user; +import com.eternalcode.parcellockers.user.repository.UserRepository; + import java.util.Collection; import java.util.Collections; import java.util.HashMap; diff --git a/src/main/java/com/eternalcode/parcellockers/user/UserPageResult.java b/src/main/java/com/eternalcode/parcellockers/user/UserPageResult.java deleted file mode 100644 index f9671366..00000000 --- a/src/main/java/com/eternalcode/parcellockers/user/UserPageResult.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.eternalcode.parcellockers.user; - -import java.util.List; - -public record UserPageResult(List users, boolean hasNextPage) { - -} diff --git a/src/main/java/com/eternalcode/parcellockers/user/UserRepositoryImpl.java b/src/main/java/com/eternalcode/parcellockers/user/UserRepositoryImpl.java deleted file mode 100644 index 00c6fb3b..00000000 --- a/src/main/java/com/eternalcode/parcellockers/user/UserRepositoryImpl.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.eternalcode.parcellockers.user; - -import com.eternalcode.parcellockers.database.AbstractDatabaseService; -import com.eternalcode.parcellockers.shared.Page; -import org.jetbrains.annotations.NotNull; - -import javax.sql.DataSource; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -public class UserRepositoryImpl extends AbstractDatabaseService implements UserRepository { - - private final Map usersByUUID = new HashMap<>(); - private final Map usersByName = new HashMap<>(); - - public UserRepositoryImpl(DataSource dataSource) { - super(dataSource); - - this.initTable(); - } - - private void initTable() { - this.executeSync("CREATE TABLE IF NOT EXISTS `users`(" + - "uuid VARCHAR(36) NOT NULL, " + - "name VARCHAR(16) NOT NULL, " + - "PRIMARY KEY (uuid)" + - ");", PreparedStatement::execute); - } - - @Override - public CompletableFuture> getUser(UUID uuid) { - User user = this.usersByUUID.get(uuid); - - if (user != null) { - return CompletableFuture.completedFuture(Optional.of(user)); - } - - return this.supplyExecute("SELECT * FROM `users` WHERE `uuid` = ?;", statement -> { - statement.setString(1, uuid.toString()); - return this.extractUser(statement); - }); - } - - @Override - public CompletableFuture> getUser(String name) { - User user = this.usersByName.get(name); - - if (user != null) { - return CompletableFuture.completedFuture(Optional.of(user)); - } - - return this.supplyExecute("SELECT * FROM `users` WHERE `name` = ?;", statement -> { - statement.setString(1, name); - return this.extractUser(statement); - }); - } - - @Override - public CompletableFuture save(User user) { - this.usersByUUID.put(user.uuid(), user); - this.usersByName.put(user.name(), user); - - return this.execute("INSERT INTO `users`(uuid, name) VALUES (?, ?);", statement -> { - statement.setString(1, user.uuid().toString()); - statement.setString(2, user.name()); - statement.execute(); - }); - } - - @Override - public CompletableFuture changeName(UUID uuid, String newName) { - User user = this.usersByUUID.get(uuid); - - if (user == null) { - return CompletableFuture.completedFuture(null); - } - - this.usersByName.remove(user.name()); - user = new User(uuid, newName); - this.usersByName.put(newName, user); - this.usersByUUID.put(uuid, user); - - return this.execute("UPDATE `users` SET `name` = ? WHERE `uuid` = ?;", statement -> { - statement.setString(1, newName); - statement.setString(2, uuid.toString()); - statement.execute(); - }); - } - - @Override - public CompletableFuture getPage(Page page) { - return this.supplyExecute("SELECT * FROM `users` LIMIT ?, ?;", statement -> { - statement.setInt(1, page.getOffset()); - statement.setInt(2, page.getLimit()); - ResultSet resultSet = statement.executeQuery(); - - List users = new ArrayList<>(); - - while (resultSet.next()) { - User user = new User(UUID.fromString(resultSet.getString("uuid")), resultSet.getString("name")); - this.usersByUUID.put(user.uuid(), user); - this.usersByName.put(user.name(), user); - users.add(user); - } - - boolean hasNext = users.size() > page.getLimit(); - if (hasNext) { - users.remove(users.size() - 1); - } - - return new UserPageResult(users, hasNext); - }); - } - - @NotNull - private Optional extractUser(PreparedStatement statement) throws SQLException { - ResultSet resultSet = statement.executeQuery(); - - if (!resultSet.next()) { - return Optional.empty(); - } - - User newUser = new User(UUID.fromString(resultSet.getString("uuid")), resultSet.getString("name")); - this.usersByUUID.put(newUser.uuid(), newUser); - this.usersByName.put(newUser.name(), newUser); - - return Optional.of(newUser); - } -} diff --git a/src/main/java/com/eternalcode/parcellockers/user/repository/UserPageResult.java b/src/main/java/com/eternalcode/parcellockers/user/repository/UserPageResult.java new file mode 100644 index 00000000..38a9bf15 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/user/repository/UserPageResult.java @@ -0,0 +1,9 @@ +package com.eternalcode.parcellockers.user.repository; + +import com.eternalcode.parcellockers.user.User; + +import java.util.List; + +public record UserPageResult(List users, boolean hasNextPage) { + +} diff --git a/src/main/java/com/eternalcode/parcellockers/user/UserRepository.java b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepository.java similarity index 82% rename from src/main/java/com/eternalcode/parcellockers/user/UserRepository.java rename to src/main/java/com/eternalcode/parcellockers/user/repository/UserRepository.java index 9f0600cf..406a8858 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/UserRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepository.java @@ -1,6 +1,7 @@ -package com.eternalcode.parcellockers.user; +package com.eternalcode.parcellockers.user.repository; import com.eternalcode.parcellockers.shared.Page; +import com.eternalcode.parcellockers.user.User; import java.util.Optional; import java.util.UUID; diff --git a/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java new file mode 100644 index 00000000..d4c862c4 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java @@ -0,0 +1,76 @@ +package com.eternalcode.parcellockers.user.repository; + +import com.eternalcode.commons.scheduler.Scheduler; +import com.eternalcode.parcellockers.database.DatabaseManager; +import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; +import com.eternalcode.parcellockers.shared.Page; +import com.eternalcode.parcellockers.user.User; +import com.j256.ormlite.table.TableUtils; +import io.sentry.Sentry; + +import java.sql.SQLException; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +public class UserRepositoryOrmLite extends AbstractRepositoryOrmLite implements UserRepository { + + public UserRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); + + try { + TableUtils.createTableIfNotExists(databaseManager.connectionSource(), UserWrapper.class); + } catch (SQLException exception) { + Sentry.captureException(exception); + exception.printStackTrace(); + } + } + + @Override + public CompletableFuture> getUser(UUID uuid) { + return this.select(UserWrapper.class, uuid).thenApply(userWrapper -> Optional.ofNullable(userWrapper.toUser())); + } + + @Override + public CompletableFuture> getUser(String name) { + return this.action(UserWrapper.class, dao -> { + UserWrapper userWrapper = dao.queryForEq("username", name).stream().findFirst().orElse(null); + return Optional.ofNullable(userWrapper).map(UserWrapper::toUser); + }); + } + + @Override + public CompletableFuture save(User user) { + return this.save(UserWrapper.class, UserWrapper.from(user)).thenApply(dao -> null); + } + + @Override + public CompletableFuture changeName(UUID uuid, String newName) { + return this.action(UserWrapper.class, dao -> { + UserWrapper userWrapper = dao.queryForId(uuid); + userWrapper.setUsername(newName); + dao.update(userWrapper); + return null; + }); + } + + @Override + public CompletableFuture getPage(Page page) { + return this.action(UserWrapper.class, dao -> { + List users = dao.queryBuilder() + .offset((long) page.getOffset()) + .limit((long) page.getLimit()) + .query() + .stream().map(UserWrapper::toUser) + .collect(Collectors.toList()); + + boolean hasNext = users.size() > page.getLimit(); + if (hasNext) { + users.remove(users.size() - 1); + } + return new UserPageResult(users, hasNext); + }); + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java b/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java new file mode 100644 index 00000000..7c1733b2 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java @@ -0,0 +1,37 @@ +package com.eternalcode.parcellockers.user.repository; + +import com.eternalcode.parcellockers.user.User; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import java.util.UUID; + +@DatabaseTable(tableName = "users") +class UserWrapper { + + @DatabaseField(id = true) + private UUID uuid; + + @DatabaseField + private String username; + + UserWrapper() { + } + + UserWrapper(UUID uuid, String username) { + this.uuid = uuid; + this.username = username; + } + + static UserWrapper from(User user) { + return new UserWrapper(user.uuid(), user.name()); + } + + public void setUsername(String username) { + this.username = username; + } + + User toUser() { + return new User(this.uuid, this.username); + } +} diff --git a/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java b/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java index c1383db8..98573f4d 100644 --- a/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java +++ b/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java @@ -4,7 +4,6 @@ import com.eternalcode.parcellockers.parcel.ParcelSize; import com.eternalcode.parcellockers.parcel.repository.ParcelPageResult; import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; -import com.eternalcode.parcellockers.parcel.repository.ParcelRepositoryImpl; import com.eternalcode.parcellockers.shared.Page; import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.Test; From b13613c734ff1041525734e1b4d8cfc8377df3ce Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:02:38 +0100 Subject: [PATCH 07/43] Add ParcelContent ORMLite implementation --- .../parcellockers/ParcelLockers.java | 4 +- .../repository/ParcelContentRepository.java | 2 +- .../ParcelContentRepositoryImpl.java | 61 ------------------- .../ParcelContentRepositoryOrmLite.java | 48 +++++++++++++++ .../repository/ParcelContentWrapper.java | 36 +++++++++++ 5 files changed, 87 insertions(+), 64 deletions(-) delete mode 100644 src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryImpl.java create mode 100644 src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java create mode 100644 src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index 3ba6ccf0..cf1bd4ff 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -9,7 +9,7 @@ import com.eternalcode.parcellockers.configuration.ConfigurationManager; import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; import com.eternalcode.parcellockers.content.repository.ParcelContentRepository; -import com.eternalcode.parcellockers.content.repository.ParcelContentRepositoryImpl; +import com.eternalcode.parcellockers.content.repository.ParcelContentRepositoryOrmLite; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.gui.implementation.locker.LockerMainGUI; import com.eternalcode.parcellockers.gui.implementation.remote.MainGUI; @@ -136,7 +136,7 @@ public void onEnable() { UserRepository userRepository = new UserRepositoryOrmLite(databaseManager, scheduler); UserManager userManager = new UserManager(userRepository); - ParcelContentRepository parcelContentRepository = new ParcelContentRepositoryImpl(dataSource); + ParcelContentRepository parcelContentRepository = new ParcelContentRepositoryOrmLite(databaseManager, scheduler); MainGUI mainGUI = new MainGUI(this, server, miniMessage, config, parcelRepository, lockerRepository, userManager); ParcelListGUI parcelListGUI = new ParcelListGUI(this, server, miniMessage, config, parcelRepository, lockerRepository, userManager, mainGUI); diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java index 52ce6a6c..54cf3389 100644 --- a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java @@ -10,7 +10,7 @@ public interface ParcelContentRepository { CompletableFuture save(ParcelContent parcelContent); - CompletableFuture remove(UUID uniqueId); + CompletableFuture remove(UUID uniqueId); CompletableFuture update(ParcelContent parcelContent); diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryImpl.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryImpl.java deleted file mode 100644 index 278e0b9c..00000000 --- a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.eternalcode.parcellockers.content.repository; - -import com.eternalcode.parcellockers.content.ParcelContent; -import com.eternalcode.parcellockers.database.AbstractDatabaseService; -import com.eternalcode.parcellockers.util.ItemSerdesUtil; - -import javax.sql.DataSource; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -public class ParcelContentRepositoryImpl extends AbstractDatabaseService implements ParcelContentRepository { - - public ParcelContentRepositoryImpl(DataSource dataSource) { - super(dataSource); - - this.initTable(); - } - - private void initTable() { - this.executeSync("CREATE TABLE IF NOT EXISTS `parcel_content`(`uuid` VARCHAR(36) NOT NULL, `items` BLOB NULL, PRIMARY KEY (uuid));", PreparedStatement::execute); - } - - @Override - public CompletableFuture save(ParcelContent parcelContent) { - return this.execute("INSERT INTO `parcel_content`(`uuid`, `items`) VALUES (?, ?)", statement -> { - statement.setString(1, parcelContent.uniqueId().toString()); - statement.setString(2, ItemSerdesUtil.serializeItems(parcelContent.items())); - statement.execute(); - }); - } - - @Override - public CompletableFuture remove(UUID uniqueId) { - return this.execute("DELETE FROM `parcel_content` WHERE `uuid` = ?", statement -> { - statement.setString(1, uniqueId.toString()); - statement.execute(); - }); - } - - @Override - public CompletableFuture update(ParcelContent parcelContent) { - return this.execute("UPDATE `parcel_content` SET `items` = ? WHERE `uuid` = ?", statement -> { - statement.setString(1, ItemSerdesUtil.serializeItems(parcelContent.items())); - statement.setString(2, parcelContent.uniqueId().toString()); - statement.execute(); - }); - } - - @Override - public CompletableFuture> find(UUID uniqueId) { - return this.supplyExecute("SELECT * FROM `parcel_content` WHERE `uuid` = ?", statement -> { - statement.setString(1, uniqueId.toString()); - ResultSet resultSet = statement.executeQuery(); - return Optional.of(new ParcelContent(uniqueId, ItemSerdesUtil.deserializeItems(resultSet.getString("items")))); - }); - } - -} diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java new file mode 100644 index 00000000..511622db --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java @@ -0,0 +1,48 @@ +package com.eternalcode.parcellockers.content.repository; + +import com.eternalcode.commons.scheduler.Scheduler; +import com.eternalcode.parcellockers.content.ParcelContent; +import com.eternalcode.parcellockers.database.DatabaseManager; +import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; +import com.j256.ormlite.table.TableUtils; +import io.sentry.Sentry; + +import java.sql.SQLException; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class ParcelContentRepositoryOrmLite extends AbstractRepositoryOrmLite implements ParcelContentRepository { + + public ParcelContentRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); + + try { + TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ParcelContentWrapper.class); + } catch (SQLException exception) { + Sentry.captureException(exception); + exception.printStackTrace(); + } + } + + + @Override + public CompletableFuture save(ParcelContent parcelContent) { + return this.saveIfNotExist(ParcelContentWrapper.class, ParcelContentWrapper.from(parcelContent)).thenApply(dao -> null); + } + + @Override + public CompletableFuture remove(UUID uniqueId) { + return this.deleteById(ParcelContentWrapper.class, uniqueId); + } + + @Override + public CompletableFuture update(ParcelContent parcelContent) { + return this.save(ParcelContentWrapper.class, ParcelContentWrapper.from(parcelContent)).thenApply(dao -> null); + } + + @Override + public CompletableFuture> find(UUID uniqueId) { + return this.select(ParcelContentWrapper.class, uniqueId).thenApply(parcelContentWrapper -> Optional.ofNullable(parcelContentWrapper.toParcelContent())); + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java new file mode 100644 index 00000000..f8c9e943 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java @@ -0,0 +1,36 @@ +package com.eternalcode.parcellockers.content.repository; + +import com.eternalcode.parcellockers.content.ParcelContent; +import com.eternalcode.parcellockers.database.persister.ItemStackPersister; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; +import org.bukkit.inventory.ItemStack; + +import java.util.List; +import java.util.UUID; + +@DatabaseTable(tableName = "parcel_content") +public class ParcelContentWrapper { + + @DatabaseField(id = true) + private UUID uniqueId; + + @DatabaseField(persisterClass = ItemStackPersister.class) + private List content; + + ParcelContentWrapper() { + } + + ParcelContentWrapper(UUID uniqueId, List content) { + this.uniqueId = uniqueId; + this.content = content; + } + + static ParcelContentWrapper from(ParcelContent parcelContent) { + return new ParcelContentWrapper(parcelContent.uniqueId(), parcelContent.items()); + } + + ParcelContent toParcelContent() { + return new ParcelContent(this.uniqueId, this.content); + } +} From 953942afd19260536fa711d0e5545650925b2871 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 15 Nov 2024 20:31:31 +0100 Subject: [PATCH 08/43] Use CompletableFuture#runAsync instead of scheduler one. Delete legacy database classes --- .../parcellockers/ParcelLockers.java | 10 +-- .../ParcelContentRepositoryOrmLite.java | 5 +- .../database/AbstractDatabaseService.java | 71 ------------------- .../database/DataSourceFactory.java | 41 ----------- .../wrapper/AbstractRepositoryOrmLite.java | 10 +-- .../ItemStorageRepositoryOrmLite.java | 5 +- .../repository/LockerRepositoryOrmLite.java | 5 +- .../repository/ParcelRepositoryOrmLite.java | 5 +- .../repository/UserRepositoryOrmLite.java | 5 +- 9 files changed, 20 insertions(+), 137 deletions(-) delete mode 100644 src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java delete mode 100644 src/main/java/com/eternalcode/parcellockers/database/DataSourceFactory.java diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index cf1bd4ff..c988e482 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -125,18 +125,18 @@ public void onEnable() { .threadPool(20) .build(); - LockerRepositoryOrmLite lockerRepository = new LockerRepositoryOrmLite(databaseManager, scheduler); + LockerRepositoryOrmLite lockerRepository = new LockerRepositoryOrmLite(databaseManager); lockerRepository.updateCaches(); - ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryOrmLite(databaseManager, scheduler); + ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryOrmLite(databaseManager); - ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager, scheduler); + ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager); ParcelManager parcelManager = new ParcelManager(config, announcer, parcelRepository); - UserRepository userRepository = new UserRepositoryOrmLite(databaseManager, scheduler); + UserRepository userRepository = new UserRepositoryOrmLite(databaseManager); UserManager userManager = new UserManager(userRepository); - ParcelContentRepository parcelContentRepository = new ParcelContentRepositoryOrmLite(databaseManager, scheduler); + ParcelContentRepository parcelContentRepository = new ParcelContentRepositoryOrmLite(databaseManager); MainGUI mainGUI = new MainGUI(this, server, miniMessage, config, parcelRepository, lockerRepository, userManager); ParcelListGUI parcelListGUI = new ParcelListGUI(this, server, miniMessage, config, parcelRepository, lockerRepository, userManager, mainGUI); diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java index 511622db..b98ed712 100644 --- a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java @@ -1,6 +1,5 @@ package com.eternalcode.parcellockers.content.repository; -import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.content.ParcelContent; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; @@ -14,8 +13,8 @@ public class ParcelContentRepositoryOrmLite extends AbstractRepositoryOrmLite implements ParcelContentRepository { - public ParcelContentRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { - super(databaseManager, scheduler); + public ParcelContentRepositoryOrmLite(DatabaseManager databaseManager) { + super(databaseManager); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ParcelContentWrapper.class); diff --git a/src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java b/src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java deleted file mode 100644 index e74a7e44..00000000 --- a/src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.eternalcode.parcellockers.database; - -import com.eternalcode.parcellockers.exception.ParcelLockersException; -import io.sentry.Sentry; -import panda.std.function.ThrowingConsumer; -import panda.std.function.ThrowingFunction; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -public abstract class AbstractDatabaseService { - - private static final AtomicInteger EXECUTOR_COUNT = new AtomicInteger(); - protected final DataSource dataSource; - private final ExecutorService executorService = Executors.newCachedThreadPool(runnable -> { - Thread thread = new Thread(runnable); - thread.setName("DATABASE-EXECUTOR-" + EXECUTOR_COUNT.incrementAndGet()); - thread.setDaemon(true); - thread.setUncaughtExceptionHandler((t, e) -> { - e.printStackTrace(); - Sentry.captureException(e); - }); - return thread; - }); - - protected AbstractDatabaseService(DataSource dataSource) { - this.dataSource = dataSource; - } - - // for void-like (removing, inserting, updating) - protected CompletableFuture execute(String sql, ThrowingConsumer consumer) { - return this.supplyExecute(sql, statement -> { - consumer.accept(statement); - return null; - }); - } - - // for selecting - protected CompletableFuture supplyExecute(String sql, ThrowingFunction function) { - return CompletableFuture.supplyAsync(() -> { - try (Connection connection = this.dataSource.getConnection(); - PreparedStatement statement = connection.prepareStatement(sql) - ) { - return function.apply(statement); - } - catch (SQLException e) { - throw new ParcelLockersException(e); - } - }, this.executorService).orTimeout(5, TimeUnit.SECONDS); - } - - // for creating tables only (see TableUtils) - protected T executeSync(String sql, ThrowingFunction function) { - try (Connection connection = this.dataSource.getConnection(); - PreparedStatement statement = connection.prepareStatement(sql) - ) { - return function.apply(statement); - } - catch (SQLException e) { - throw new ParcelLockersException(e); - } - } - -} diff --git a/src/main/java/com/eternalcode/parcellockers/database/DataSourceFactory.java b/src/main/java/com/eternalcode/parcellockers/database/DataSourceFactory.java deleted file mode 100644 index 5de0412d..00000000 --- a/src/main/java/com/eternalcode/parcellockers/database/DataSourceFactory.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.eternalcode.parcellockers.database; - -import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; - -import java.io.File; - -public class DataSourceFactory { - - private DataSourceFactory() { - } - - public static HikariDataSource buildHikariDataSource(PluginConfiguration databaseConfig, File dataFolder) { - HikariConfig hikariConfig = new HikariConfig(); - - hikariConfig.addDataSourceProperty("cachePrepStmts", "true"); - hikariConfig.addDataSourceProperty("prepStmtCacheSize", "250"); - hikariConfig.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); - hikariConfig.addDataSourceProperty("useServerPrepStmts", true); - - PluginConfiguration.Settings settings = databaseConfig.settings; - switch (settings.databaseType) { - case MYSQL -> { - hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver"); - hikariConfig.setJdbcUrl("jdbc:mysql://" + settings.host + ":" + settings.port + "/" + settings.databaseName + "?useSSL=" + settings.useSSL); - hikariConfig.setUsername(settings.user); - hikariConfig.setPassword(settings.password); - } - - case SQLITE -> { - hikariConfig.setDriverClassName("org.sqlite.JDBC"); - hikariConfig.setJdbcUrl("jdbc:sqlite:" + dataFolder + "/database.db"); - } - default -> throw new IllegalStateException("Unexpected value: " + settings.databaseType); - } - - return new HikariDataSource(hikariConfig); - } - -} diff --git a/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java index 5a6941ca..dc9babae 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java @@ -1,8 +1,8 @@ package com.eternalcode.parcellockers.database.wrapper; -import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.j256.ormlite.dao.Dao; +import io.sentry.Sentry; import panda.std.function.ThrowingFunction; import java.sql.SQLException; @@ -13,11 +13,9 @@ public abstract class AbstractRepositoryOrmLite { protected final DatabaseManager databaseManager; - protected final Scheduler scheduler; - protected AbstractRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + protected AbstractRepositoryOrmLite(DatabaseManager databaseManager) { this.databaseManager = databaseManager; - this.scheduler = scheduler; } protected CompletableFuture save(Class type, T warp) { @@ -55,14 +53,16 @@ protected CompletableFuture> selectAll(Class type) { protected CompletableFuture action(Class type, ThrowingFunction, R, SQLException> action) { CompletableFuture completableFuture = new CompletableFuture<>(); - this.scheduler.runAsync(() -> { + CompletableFuture.runAsync(() -> { Dao dao = this.databaseManager.getDao(type); try { completableFuture.complete(action.apply(dao)); } catch (Throwable throwable) { + Sentry.captureException(throwable); completableFuture.completeExceptionally(throwable); + throwable.printStackTrace(); } }); diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java index 4e5a4ff2..42c99386 100644 --- a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java @@ -1,6 +1,5 @@ package com.eternalcode.parcellockers.itemstorage.repository; -import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; import com.eternalcode.parcellockers.itemstorage.ItemStorage; @@ -14,8 +13,8 @@ public class ItemStorageRepositoryOrmLite extends AbstractRepositoryOrmLite implements ItemStorageRepository { - public ItemStorageRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { - super(databaseManager, scheduler); + public ItemStorageRepositoryOrmLite(DatabaseManager databaseManager) { + super(databaseManager); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ItemStorageWrapper.class); diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java index fe28beb2..c3bd55fe 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -1,6 +1,5 @@ package com.eternalcode.parcellockers.locker.repository; -import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; import com.eternalcode.parcellockers.locker.Locker; @@ -24,8 +23,8 @@ public class LockerRepositoryOrmLite extends AbstractRepositoryOrmLite implement private final Map cache = new HashMap<>(); private final Map positionCache = new HashMap<>(); - public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { - super(databaseManager, scheduler); + public LockerRepositoryOrmLite(DatabaseManager databaseManager) { + super(databaseManager); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), LockerWrapper.class); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index 26f2bae7..8901ff66 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -1,6 +1,5 @@ package com.eternalcode.parcellockers.parcel.repository; -import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; import com.eternalcode.parcellockers.parcel.Parcel; @@ -25,8 +24,8 @@ public class ParcelRepositoryOrmLite extends AbstractRepositoryOrmLite implement private final Map cache = new HashMap<>(); - public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { - super(databaseManager, scheduler); + public ParcelRepositoryOrmLite(DatabaseManager databaseManager) { + super(databaseManager); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ParcelWrapper.class); diff --git a/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java index d4c862c4..7286512a 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java @@ -1,6 +1,5 @@ package com.eternalcode.parcellockers.user.repository; -import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; import com.eternalcode.parcellockers.shared.Page; @@ -17,8 +16,8 @@ public class UserRepositoryOrmLite extends AbstractRepositoryOrmLite implements UserRepository { - public UserRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { - super(databaseManager, scheduler); + public UserRepositoryOrmLite(DatabaseManager databaseManager) { + super(databaseManager); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), UserWrapper.class); From d8b5f025dfc0ab2eddab26e861884ba2ae121ead Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 15 Nov 2024 20:31:47 +0100 Subject: [PATCH 09/43] Set more DatabaseManager properties --- .../com/eternalcode/parcellockers/database/DatabaseManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java b/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java index 59251429..1e466a78 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java +++ b/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java @@ -45,6 +45,8 @@ public void connect() throws SQLException { this.dataSource.addDataSourceProperty("useServerPrepStmts", true); this.dataSource.setMaximumPoolSize(5); + this.dataSource.setConnectionTimeout(5000); + this.dataSource.setLeakDetectionThreshold(5000); this.dataSource.setUsername(this.config.settings.user); this.dataSource.setPassword(this.config.settings.password); From 4504529c51a81d1bc658a15750c3ef64bfd98405 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Thu, 26 Dec 2024 18:20:41 +0100 Subject: [PATCH 10/43] Fix integration tests --- .../ParcelDatabaseServiceIntegrationTest.java | 13 ++++++++++--- ...arcelLockerDatabaseServiceIntegrationTest.java | 13 +++++++++---- .../database/ParcelLockerIntegrationSpec.java | 15 --------------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java b/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java index 98573f4d..8c982be2 100644 --- a/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java +++ b/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java @@ -1,22 +1,26 @@ package com.eternalcode.parcellockers.database; +import com.eternalcode.parcellockers.configuration.ConfigurationManager; +import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; import com.eternalcode.parcellockers.parcel.Parcel; import com.eternalcode.parcellockers.parcel.ParcelSize; import com.eternalcode.parcellockers.parcel.repository.ParcelPageResult; import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; +import com.eternalcode.parcellockers.parcel.repository.ParcelRepositoryOrmLite; import com.eternalcode.parcellockers.shared.Page; -import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.Test; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.utility.DockerImageName; +import java.io.File; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.logging.Logger; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -29,8 +33,11 @@ class ParcelDatabaseServiceIntegrationTest extends ParcelLockerIntegrationSpec { @Test void test() { - HikariDataSource dataSource = buildHikariDataSource(mySQLContainer); - ParcelRepository parcelRepository = new ParcelRepositoryImpl(dataSource); + File dataFolder = new File("run/plugins/ParcelLockers"); + PluginConfiguration config = new ConfigurationManager(dataFolder).load(new PluginConfiguration()); + DatabaseManager databaseManager = new DatabaseManager(config, Logger.getLogger("ParcelLockers"), dataFolder); + + ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager); UUID uuid = UUID.randomUUID(); UUID sender = UUID.randomUUID(); UUID receiver = UUID.randomUUID(); diff --git a/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java b/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java index 9923363e..db4ae9de 100644 --- a/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java +++ b/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java @@ -1,20 +1,23 @@ package com.eternalcode.parcellockers.database; +import com.eternalcode.parcellockers.configuration.ConfigurationManager; +import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; import com.eternalcode.parcellockers.locker.Locker; import com.eternalcode.parcellockers.locker.repository.LockerPageResult; import com.eternalcode.parcellockers.locker.repository.LockerRepository; -import com.eternalcode.parcellockers.locker.repository.LockerRepositoryImpl; +import com.eternalcode.parcellockers.locker.repository.LockerRepositoryOrmLite; import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.shared.Position; -import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.Test; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.utility.DockerImageName; +import java.io.File; import java.util.Optional; import java.util.UUID; +import java.util.logging.Logger; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -27,9 +30,11 @@ class ParcelLockerDatabaseServiceIntegrationTest extends ParcelLockerIntegration @Test void test() { - HikariDataSource dataSource = buildHikariDataSource(mySQLContainer); + File dataFolder = new File("run/plugins/ParcelLockers"); + PluginConfiguration config = new ConfigurationManager(dataFolder).load(new PluginConfiguration()); + DatabaseManager databaseManager = new DatabaseManager(config, Logger.getLogger("ParcelLockers"), dataFolder); - LockerRepository parcelLockerRepository = new LockerRepositoryImpl(dataSource); + LockerRepository parcelLockerRepository = new LockerRepositoryOrmLite(databaseManager); UUID uuid = UUID.randomUUID(); String description = "Parcel locker description."; diff --git a/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerIntegrationSpec.java b/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerIntegrationSpec.java index b9f85a5a..02bf6da7 100644 --- a/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerIntegrationSpec.java +++ b/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerIntegrationSpec.java @@ -1,9 +1,5 @@ package com.eternalcode.parcellockers.database; -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import org.testcontainers.containers.MySQLContainer; - import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -14,15 +10,4 @@ T await(CompletableFuture future) { .orTimeout(5, TimeUnit.SECONDS) .join(); } - - static HikariDataSource buildHikariDataSource(MySQLContainer mySQLContainer) { - HikariConfig hikariConfig = new HikariConfig(); - - hikariConfig.setDriverClassName(mySQLContainer.getDriverClassName()); - hikariConfig.setJdbcUrl(mySQLContainer.getJdbcUrl()); - hikariConfig.setUsername(mySQLContainer.getUsername()); - hikariConfig.setPassword(mySQLContainer.getPassword()); - - return new HikariDataSource(hikariConfig); - } } From ad6b9080b7acb2da6e0af41d8adaa17aa22d9489 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Thu, 26 Dec 2024 18:22:24 +0100 Subject: [PATCH 11/43] Update TODO --- TODO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 82c15049..4e889b1d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,6 @@ ## 📝 TODO -- [ ] Add support for more databases (H2, PostgreSQL, MongoDB?) +- [x] Add support for more databases (H2, PostgreSQL, MongoDB?) - [ ] Add translation system, more languages - [ ] Add delivery codes, so any person knowing the code can pick up the parcel - [ ] Add delivery time, so the parcel can be picked up only in a specific time From 76e592e63dd6bebb16a07e55e9af52b9067bd47e Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Thu, 26 Dec 2024 18:23:52 +0100 Subject: [PATCH 12/43] Update version in Gradle --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a13f902e..3bb02fef 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -130,7 +130,7 @@ tasks.withType { tasks { runServer { - minecraftVersion("1.21.1") + minecraftVersion("1.21.4") } test { @@ -138,7 +138,7 @@ tasks { } shadowJar { - archiveFileName.set("ParcelLockers v${project.version} (MC 1.8.8-1.21.x).jar") + archiveFileName.set("ParcelLockers v${project.version} (MC 1.17.x-1.21.x).jar") exclude( "org/intellij/lang/annotations/**", From ea901eea131cd4e86384e8f5255a6b873cb8b15f Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Thu, 26 Dec 2024 18:53:59 +0100 Subject: [PATCH 13/43] Fix cache and rename getInstance to getSingleton in persister classes --- .../database/persister/ItemStackPersister.java | 2 +- .../database/persister/PositionPersister.java | 2 +- .../locker/repository/LockerRepositoryOrmLite.java | 9 ++++++--- .../parcel/repository/ParcelRepositoryOrmLite.java | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java index ed7643ba..5c238d8b 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java @@ -29,7 +29,7 @@ private ItemStackPersister() { super(SqlType.LONG_STRING, new Class[] { ItemStackPersister.class }); } - public static ItemStackPersister getInstance() { + public static ItemStackPersister getSingleton() { return instance; } diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java index 869a5d37..de9ba17f 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java @@ -16,7 +16,7 @@ private PositionPersister() { super(SqlType.LONG_STRING, new Class[] { PositionPersister.class }); } - public static PositionPersister getInstance() { + public static PositionPersister getSingleton() { return instance; } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java index c3bd55fe..e5d60152 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -36,6 +36,7 @@ public LockerRepositoryOrmLite(DatabaseManager databaseManager) { @Override public CompletableFuture save(Locker locker) { + this.addToCache(locker); return this.save(LockerWrapper.class, LockerWrapper.from(locker)).thenApply(dao -> null); } @@ -115,9 +116,11 @@ public boolean isInCache(UUID uuid) { } public void updateCaches() { - this.cache.clear(); - this.positionCache.clear(); - this.findAll().thenAccept(lockers -> lockers.forEach(this::addToCache)); + this.findAll().thenAccept(lockers -> { + this.cache.clear(); + this.positionCache.clear(); + lockers.forEach(this::addToCache); + }); } private void addToCache(Locker locker) { diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index 8901ff66..7954e2ba 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -37,6 +37,7 @@ public ParcelRepositoryOrmLite(DatabaseManager databaseManager) { @Override public CompletableFuture save(Parcel parcel) { + this.addToCache(parcel); return this.save(ParcelWrapper.class, ParcelWrapper.from(parcel)).thenApply(dao -> null); } From d99c514fc85718c3186879882f6e4d6af6ece100 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:00:53 +0100 Subject: [PATCH 14/43] Bump spigot-api to 1.21.4 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3bb02fef..6f142013 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,7 +27,7 @@ repositories { dependencies { // minecraft development api - compileOnly("org.spigotmc:spigot-api:1.21.1-R0.1-SNAPSHOT") + compileOnly("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") implementation("net.kyori:adventure-platform-bukkit:4.3.4") implementation("net.kyori:adventure-text-minimessage:4.18.0") implementation("dev.rollczi:litecommands-bukkit:3.9.5") From f433141ce8d882120370da305540f3be9241ab8d Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:15:41 +0100 Subject: [PATCH 15/43] Disable ORMLite logs --- .../eternalcode/parcellockers/ParcelLockers.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index 7b89f19e..1214b02d 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -36,6 +36,8 @@ import com.eternalcode.parcellockers.user.repository.UserRepository; import com.eternalcode.parcellockers.user.repository.UserRepositoryOrmLite; import com.google.common.base.Stopwatch; +import com.j256.ormlite.logger.LoggerFactory; +import com.j256.ormlite.logger.NullLogBackend; import dev.rollczi.litecommands.LiteCommands; import dev.rollczi.litecommands.adventure.LiteAdventureExtension; import dev.rollczi.litecommands.annotations.LiteCommandsAnnotations; @@ -102,11 +104,12 @@ public void onEnable() { options.setTag("serverVersion", this.getServer().getVersion()); options.setTag("serverSoftware", PaperLib.getEnvironment().getName()); options.setTag("plugins", Arrays.stream(server.getPluginManager().getPlugins()).toList().toString()); + options.setEnabled(false); this.getLogger().info("Sentry initialized successfully!"); }); } - //HikariDataSource dataSource = DataSourceFactory.buildHikariDataSource(config, this.getDataFolder()); + LoggerFactory.setLogBackendFactory(new NullLogBackend.NullLogBackendFactory()); DatabaseManager databaseManager = new DatabaseManager(config, this.getLogger(), this.getDataFolder()); @@ -127,6 +130,7 @@ public void onEnable() { LockerRepositoryOrmLite lockerRepository = new LockerRepositoryOrmLite(databaseManager); lockerRepository.updateCaches(); + ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryOrmLite(databaseManager); ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager); @@ -179,7 +183,9 @@ public void onEnable() { @Override public void onDisable() { - this.databaseManager.disconnect(); + if (this.databaseManager != null) { + this.databaseManager.disconnect(); + } if (this.liteCommands != null) { this.liteCommands.unregister(); @@ -199,11 +205,11 @@ private void softwareCheck() { if (!environment.isPaper()) { logger.warning("Your server running on unsupported software, please use Paper or its forks"); logger.warning("You can easily download Paper from https://papermc.io/downloads"); - logger.warning("WARNING: Supported MC versions are 1.17.x-1.19.x"); + logger.warning("WARNING: Supported MC versions are 1.17.x-1.21.x"); return; } - if (!environment.isVersion(17)) { + if (!environment.isVersion(17) || environment.isVersion(21)) { logger.warning("ParcelLockers no longer supports your version, be aware that there may be bugs!"); return; } From f708327aa7d36603a7f3410125e5cf175162eb09 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:22:39 +0100 Subject: [PATCH 16/43] Tick TODO --- TODO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 4e889b1d..2f97842f 100644 --- a/TODO.md +++ b/TODO.md @@ -8,7 +8,7 @@ - [ ] Parcel return logic - [x] Banned parcel items (configurable) - [ ] Parcel fee -- [ ] Rewrite database to ORMLite (far in future) +- [x] Rewrite database to ORMLite (far in future) - [ ] Add more parcel types (fragile, etc...) - [ ] Add option to config for parcel locker space (e.g. max parcels within a locker) - [ ] Finish GUIs From 500ad40d0a82a2b2288af08130ccc75bb1ecd902 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:41:03 +0100 Subject: [PATCH 17/43] Apply suggestion --- .../parcellockers/user/repository/UserRepositoryOrmLite.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java index 7286512a..3a601ab9 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java @@ -29,7 +29,9 @@ public UserRepositoryOrmLite(DatabaseManager databaseManager) { @Override public CompletableFuture> getUser(UUID uuid) { - return this.select(UserWrapper.class, uuid).thenApply(userWrapper -> Optional.ofNullable(userWrapper.toUser())); + return this.select(UserWrapper.class, uuid).thenApply(userWrapper -> Optional.ofNullable(userWrapper) + .map(UserWrapper::toUser) + ); } @Override From 7bb711d6cc1ecfc82bfaab89309c9ef9f3b854d0 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:49:44 +0100 Subject: [PATCH 18/43] Apply CodeRabbit suggestion regarding remove() method in ParcelRepositoryOrmLite --- .../parcel/repository/ParcelRepositoryOrmLite.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index 7954e2ba..2a77aadd 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -64,12 +64,18 @@ public CompletableFuture>> findByReceiver(UUID receiver) { @Override public CompletableFuture remove(Parcel parcel) { - return this.delete(ParcelWrapper.class, ParcelWrapper.from(parcel)); + return this.remove(parcel.uuid()); } @Override public CompletableFuture remove(UUID uuid) { - return this.deleteById(ParcelWrapper.class, uuid); + CompletableFuture removeFuture = this.deleteById(ParcelWrapper.class, uuid); + removeFuture.thenAccept(deletedCount -> { + if (deletedCount > 0) { + this.removeFromCache(uuid); + } + }); + return removeFuture; } @Override From 8b2634053dbe852c4e0cd4f369f4f78d05221c8c Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 16:56:55 +0100 Subject: [PATCH 19/43] Add TestScheduler --- .../parcellockers/TestScheduler.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/test/java/com/eternalcode/parcellockers/TestScheduler.java diff --git a/src/test/java/com/eternalcode/parcellockers/TestScheduler.java b/src/test/java/com/eternalcode/parcellockers/TestScheduler.java new file mode 100644 index 00000000..e8713ecf --- /dev/null +++ b/src/test/java/com/eternalcode/parcellockers/TestScheduler.java @@ -0,0 +1,86 @@ +package com.eternalcode.parcellockers; + +import com.eternalcode.commons.scheduler.Scheduler; +import com.eternalcode.commons.scheduler.Task; + +import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +public class TestScheduler implements Scheduler { + private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(8); + + @Override + public Task run(Runnable runnable) { + Future future = executorService.submit(runnable); + return new TestTask(future, false); + } + + @Override + public Task runAsync(Runnable runnable) { + Future future = CompletableFuture.runAsync(runnable, executorService); + return new TestTask(future, false); + } + + @Override + public Task runLater(Runnable runnable, Duration duration) { + ScheduledFuture future = executorService.schedule(runnable, duration.toMillis(), TimeUnit.MILLISECONDS); + return new TestTask(future, false); + } + + @Override + public Task runLaterAsync(Runnable runnable, Duration duration) { + ScheduledFuture future = executorService.schedule(() -> CompletableFuture.runAsync(runnable, executorService), duration.toMillis(), TimeUnit.MILLISECONDS); + return new TestTask(future, false); + } + + @Override + public Task timer(Runnable runnable, Duration initialDelay, Duration period) { + ScheduledFuture future = executorService.scheduleAtFixedRate(runnable, initialDelay.toMillis(), period.toMillis(), TimeUnit.MILLISECONDS); + return new TestTask(future, true); + } + + @Override + public Task timerAsync(Runnable runnable, Duration initialDelay, Duration period) { + ScheduledFuture future = executorService.scheduleAtFixedRate(() -> CompletableFuture.runAsync(runnable, executorService), initialDelay.toMillis(), period.toMillis(), TimeUnit.MILLISECONDS); + return new TestTask(future, true); + } + + @Override + public CompletableFuture complete(Supplier supplier) { + return CompletableFuture.supplyAsync(supplier, executorService); + } + + @Override + public CompletableFuture completeAsync(Supplier supplier) { + return CompletableFuture.supplyAsync(supplier, executorService); + } + + private record TestTask(Future future, boolean isRepeating) implements Task { + + @Override + public void cancel() { + future.cancel(false); + } + + @Override + public boolean isCanceled() { + return future.isCancelled(); + } + + @Override + public boolean isAsync() { + return future instanceof CompletableFuture; + } + + @Override + public boolean isRunning() { + return !future.isDone(); + } + } +} From 3fd2eb34032fe015d77133573d5e9fda2550f8ec Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 17:03:07 +0100 Subject: [PATCH 20/43] Revert "Use CompletableFuture#runAsync instead of scheduler one. This *partially* reverts commit 953942af --- .../com/eternalcode/parcellockers/ParcelLockers.java | 10 +++++----- .../repository/ParcelContentRepositoryOrmLite.java | 5 +++-- .../database/wrapper/AbstractRepositoryOrmLite.java | 7 +++++-- .../repository/ItemStorageRepositoryOrmLite.java | 5 +++-- .../locker/repository/LockerRepositoryOrmLite.java | 5 +++-- .../parcel/repository/ParcelRepositoryOrmLite.java | 5 +++-- .../user/repository/UserRepositoryOrmLite.java | 5 +++-- 7 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index 1214b02d..82102dd1 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -128,19 +128,19 @@ public void onEnable() { .threadPool(20) .build(); - LockerRepositoryOrmLite lockerRepository = new LockerRepositoryOrmLite(databaseManager); + LockerRepositoryOrmLite lockerRepository = new LockerRepositoryOrmLite(databaseManager, scheduler); lockerRepository.updateCaches(); - ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryOrmLite(databaseManager); + ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryOrmLite(databaseManager, scheduler); - ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager); + ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager, scheduler); ParcelManager parcelManager = new ParcelManager(config, announcer, parcelRepository); - UserRepository userRepository = new UserRepositoryOrmLite(databaseManager); + UserRepository userRepository = new UserRepositoryOrmLite(databaseManager, scheduler); UserManager userManager = new UserManager(userRepository); - ParcelContentRepository parcelContentRepository = new ParcelContentRepositoryOrmLite(databaseManager); + ParcelContentRepository parcelContentRepository = new ParcelContentRepositoryOrmLite(databaseManager, scheduler); MainGUI mainGUI = new MainGUI(this, server, miniMessage, config, parcelRepository, lockerRepository, userManager); ParcelListGUI parcelListGUI = new ParcelListGUI(this, server, miniMessage, config, parcelRepository, lockerRepository, userManager, mainGUI); diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java index b98ed712..511622db 100644 --- a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.content.repository; +import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.content.ParcelContent; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; @@ -13,8 +14,8 @@ public class ParcelContentRepositoryOrmLite extends AbstractRepositoryOrmLite implements ParcelContentRepository { - public ParcelContentRepositoryOrmLite(DatabaseManager databaseManager) { - super(databaseManager); + public ParcelContentRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ParcelContentWrapper.class); diff --git a/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java index dc9babae..53916001 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.database.wrapper; +import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.j256.ormlite.dao.Dao; import io.sentry.Sentry; @@ -13,9 +14,11 @@ public abstract class AbstractRepositoryOrmLite { protected final DatabaseManager databaseManager; + protected final Scheduler scheduler; - protected AbstractRepositoryOrmLite(DatabaseManager databaseManager) { + protected AbstractRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { this.databaseManager = databaseManager; + this.scheduler = scheduler; } protected CompletableFuture save(Class type, T warp) { @@ -53,7 +56,7 @@ protected CompletableFuture> selectAll(Class type) { protected CompletableFuture action(Class type, ThrowingFunction, R, SQLException> action) { CompletableFuture completableFuture = new CompletableFuture<>(); - CompletableFuture.runAsync(() -> { + this.scheduler.runAsync(() -> { Dao dao = this.databaseManager.getDao(type); try { diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java index 42c99386..4e5a4ff2 100644 --- a/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.itemstorage.repository; +import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; import com.eternalcode.parcellockers.itemstorage.ItemStorage; @@ -13,8 +14,8 @@ public class ItemStorageRepositoryOrmLite extends AbstractRepositoryOrmLite implements ItemStorageRepository { - public ItemStorageRepositoryOrmLite(DatabaseManager databaseManager) { - super(databaseManager); + public ItemStorageRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ItemStorageWrapper.class); diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java index e5d60152..3230d57d 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.locker.repository; +import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; import com.eternalcode.parcellockers.locker.Locker; @@ -23,8 +24,8 @@ public class LockerRepositoryOrmLite extends AbstractRepositoryOrmLite implement private final Map cache = new HashMap<>(); private final Map positionCache = new HashMap<>(); - public LockerRepositoryOrmLite(DatabaseManager databaseManager) { - super(databaseManager); + public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), LockerWrapper.class); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index 2a77aadd..ed94e3c3 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.parcel.repository; +import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; import com.eternalcode.parcellockers.parcel.Parcel; @@ -24,8 +25,8 @@ public class ParcelRepositoryOrmLite extends AbstractRepositoryOrmLite implement private final Map cache = new HashMap<>(); - public ParcelRepositoryOrmLite(DatabaseManager databaseManager) { - super(databaseManager); + public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ParcelWrapper.class); diff --git a/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java index 3a601ab9..e3edf8cb 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.user.repository; +import com.eternalcode.commons.scheduler.Scheduler; import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; import com.eternalcode.parcellockers.shared.Page; @@ -16,8 +17,8 @@ public class UserRepositoryOrmLite extends AbstractRepositoryOrmLite implements UserRepository { - public UserRepositoryOrmLite(DatabaseManager databaseManager) { - super(databaseManager); + public UserRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + super(databaseManager, scheduler); try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), UserWrapper.class); From 405ceed51b0d7e2d67c7f4f9aceaf050fd3a5ae0 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 17:09:05 +0100 Subject: [PATCH 21/43] Use ConcurrentHashMaps in caches --- .../locker/repository/LockerRepositoryOrmLite.java | 6 +++--- .../parcel/repository/ParcelRepositoryOrmLite.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java index 3230d57d..86b7ed4b 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -11,18 +11,18 @@ import java.sql.SQLException; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class LockerRepositoryOrmLite extends AbstractRepositoryOrmLite implements LockerRepository { - private final Map cache = new HashMap<>(); - private final Map positionCache = new HashMap<>(); + private final Map cache = new ConcurrentHashMap<>(); + private final Map positionCache = new ConcurrentHashMap<>(); public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { super(databaseManager, scheduler); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index ed94e3c3..971f4976 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -10,12 +10,12 @@ import java.sql.SQLException; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class ParcelRepositoryOrmLite extends AbstractRepositoryOrmLite implements ParcelRepository { @@ -23,7 +23,7 @@ public class ParcelRepositoryOrmLite extends AbstractRepositoryOrmLite implement private static final String RECEIVER_COLUMN = "receiver"; private static final String SENDER_COLUMN = "sender"; - private final Map cache = new HashMap<>(); + private final Map cache = new ConcurrentHashMap<>(); public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { super(databaseManager, scheduler); From 68680805304a7d28eed6b639e25d4ce9277e763f Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 17:19:56 +0100 Subject: [PATCH 22/43] Fix unit tests build --- .../database/ParcelDatabaseServiceIntegrationTest.java | 3 ++- .../database/ParcelLockerDatabaseServiceIntegrationTest.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java b/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java index 8c982be2..0c0bd269 100644 --- a/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java +++ b/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.database; +import com.eternalcode.parcellockers.TestScheduler; import com.eternalcode.parcellockers.configuration.ConfigurationManager; import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; import com.eternalcode.parcellockers.parcel.Parcel; @@ -37,7 +38,7 @@ void test() { PluginConfiguration config = new ConfigurationManager(dataFolder).load(new PluginConfiguration()); DatabaseManager databaseManager = new DatabaseManager(config, Logger.getLogger("ParcelLockers"), dataFolder); - ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager); + ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager, new TestScheduler()); UUID uuid = UUID.randomUUID(); UUID sender = UUID.randomUUID(); UUID receiver = UUID.randomUUID(); diff --git a/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java b/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java index db4ae9de..5c88662e 100644 --- a/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java +++ b/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.database; +import com.eternalcode.parcellockers.TestScheduler; import com.eternalcode.parcellockers.configuration.ConfigurationManager; import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; import com.eternalcode.parcellockers.locker.Locker; @@ -34,7 +35,7 @@ void test() { PluginConfiguration config = new ConfigurationManager(dataFolder).load(new PluginConfiguration()); DatabaseManager databaseManager = new DatabaseManager(config, Logger.getLogger("ParcelLockers"), dataFolder); - LockerRepository parcelLockerRepository = new LockerRepositoryOrmLite(databaseManager); + LockerRepository parcelLockerRepository = new LockerRepositoryOrmLite(databaseManager, new TestScheduler()); UUID uuid = UUID.randomUUID(); String description = "Parcel locker description."; From 0c700be2392e27188b4946c4a2f5f3305baf86e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 17:32:56 +0100 Subject: [PATCH 23/43] Update src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../com/eternalcode/parcellockers/database/DatabaseManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java b/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java index 1e466a78..bcae6ee2 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java +++ b/src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java @@ -74,7 +74,7 @@ public void connect() throws SQLException { case POSTGRESQL -> { this.dataSource.setDriverClassName("org.postgresql.Driver"); - this.dataSource.setJdbcUrl("jdbc:postgresql://" + this.config.settings.host + ":" + this.config.settings.port + "/"); + this.dataSource.setJdbcUrl("jdbc:postgresql://" + this.config.settings.host + ":" + this.config.settings.port + "/" + this.config.settings.databaseName); } default -> throw new IllegalStateException("Unexpected value: SQL type '" + databaseType + "' not found"); From cd38904c0f91984ebb4eca63d5997eea7b0912d1 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 17:46:33 +0100 Subject: [PATCH 24/43] Revert version check --- src/main/java/com/eternalcode/parcellockers/ParcelLockers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index 82102dd1..e9e258d3 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -209,7 +209,7 @@ private void softwareCheck() { return; } - if (!environment.isVersion(17) || environment.isVersion(21)) { + if (!environment.isVersion(17)) { logger.warning("ParcelLockers no longer supports your version, be aware that there may be bugs!"); return; } From ed5a455d87c78febe1c8dfd182de29f688359b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 17:47:27 +0100 Subject: [PATCH 25/43] Update src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../locker/repository/LockerRepositoryOrmLite.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java index 86b7ed4b..e2993daa 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -118,9 +118,16 @@ public boolean isInCache(UUID uuid) { public void updateCaches() { this.findAll().thenAccept(lockers -> { + Map newCache = new ConcurrentHashMap<>(); + Map newPositionCache = new ConcurrentHashMap<>(); + lockers.forEach(locker -> { + newCache.put(locker.uuid(), locker); + newPositionCache.put(locker.position(), locker.uuid()); + }); this.cache.clear(); this.positionCache.clear(); - lockers.forEach(this::addToCache); + this.cache.putAll(newCache); + this.positionCache.putAll(newPositionCache); }); } From 1137be0cc18fe3cb917a640b24692ac70a47e9dd Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 18:04:38 +0100 Subject: [PATCH 26/43] Correct order of CRUD operations --- .../repository/LockerRepositoryOrmLite.java | 19 +++++++++++++++---- .../repository/ParcelRepositoryOrmLite.java | 8 +++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java index e2993daa..7f307381 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -37,8 +37,10 @@ public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler schedu @Override public CompletableFuture save(Locker locker) { - this.addToCache(locker); - return this.save(LockerWrapper.class, LockerWrapper.from(locker)).thenApply(dao -> null); + return this.save(LockerWrapper.class, LockerWrapper.from(locker)).thenApply(dao -> { + this.addToCache(locker); + return null; + }); } @Override @@ -64,12 +66,21 @@ public CompletableFuture> findByPosition(Position position) { @Override public CompletableFuture remove(UUID uuid) { - return this.deleteById(LockerWrapper.class, uuid); + return this.deleteById(LockerWrapper.class, uuid) + .thenApply(result -> { + if (result > 0) { + Locker locker = this.cache.remove(uuid); + if (locker != null) { + this.positionCache.remove(locker.position()); + } + } + return result; + }); } @Override public CompletableFuture remove(Locker locker) { - return this.action(LockerWrapper.class, dao -> dao.delete(LockerWrapper.from(locker))); + return this.remove(locker.uuid()); } @Override diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index 971f4976..77cbb34d 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -38,8 +38,10 @@ public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler schedu @Override public CompletableFuture save(Parcel parcel) { - this.addToCache(parcel); - return this.save(ParcelWrapper.class, ParcelWrapper.from(parcel)).thenApply(dao -> null); + return this.save(ParcelWrapper.class, ParcelWrapper.from(parcel)).thenApply(dao -> { + this.addToCache(parcel); + return null; + }); } @Override @@ -112,6 +114,6 @@ private void removeFromCache(UUID uuid) { @Override public Optional findParcel(UUID uuid) { - return Optional.of(this.cache.get(uuid)); + return Optional.ofNullable(this.cache.get(uuid)); } } From 7ddc481f7bf35a29459856fab40f303e1bde9d1b Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 18:06:44 +0100 Subject: [PATCH 27/43] Correct isAsync method --- src/test/java/com/eternalcode/parcellockers/TestScheduler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/eternalcode/parcellockers/TestScheduler.java b/src/test/java/com/eternalcode/parcellockers/TestScheduler.java index e8713ecf..f4c0a1e9 100644 --- a/src/test/java/com/eternalcode/parcellockers/TestScheduler.java +++ b/src/test/java/com/eternalcode/parcellockers/TestScheduler.java @@ -75,7 +75,7 @@ public boolean isCanceled() { @Override public boolean isAsync() { - return future instanceof CompletableFuture; + return future instanceof CompletableFuture || future instanceof ScheduledFuture; } @Override From 602d3531b91c7519edbefb8847f155a9ca65a68b Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 31 Dec 2024 18:13:00 +0100 Subject: [PATCH 28/43] Make locker positions unique --- .../parcellockers/locker/repository/LockerWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java index af9d476c..3682d80b 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java @@ -17,7 +17,7 @@ class LockerWrapper { @DatabaseField(columnName = "description") private String description; - @DatabaseField(columnName = "position", persisterClass = PositionPersister.class) + @DatabaseField(columnName = "position", persisterClass = PositionPersister.class, unique = true) private Position position; LockerWrapper() { From 93ef8e479aa12eb3cd8e2d69453b24a50c8d8320 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 10 Jan 2025 22:11:49 +0100 Subject: [PATCH 29/43] Rename warp to entity --- .../database/wrapper/AbstractRepositoryOrmLite.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java index 53916001..e061b07c 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java @@ -21,12 +21,12 @@ protected AbstractRepositoryOrmLite(DatabaseManager databaseManager, Scheduler s this.scheduler = scheduler; } - protected CompletableFuture save(Class type, T warp) { - return this.action(type, dao -> dao.createOrUpdate(warp)); + protected CompletableFuture save(Class type, T entity) { + return this.action(type, dao -> dao.createOrUpdate(entity)); } - protected CompletableFuture saveIfNotExist(Class type, T warp) { - return this.action(type, dao -> dao.createIfNotExists(warp)); + protected CompletableFuture saveIfNotExist(Class type, T entity) { + return this.action(type, dao -> dao.createIfNotExists(entity)); } protected CompletableFuture select(Class type, ID id) { @@ -37,8 +37,8 @@ protected CompletableFuture> selectSafe(Class type, ID id return this.action(type, dao -> Optional.ofNullable(dao.queryForId(id))); } - protected CompletableFuture delete(Class type, T warp) { - return this.action(type, dao -> dao.delete(warp)); + protected CompletableFuture delete(Class type, T entity) { + return this.action(type, dao -> dao.delete(entity)); } protected CompletableFuture deleteAll(Class type) { From 8c5959b268328ec9cbb8f5d7cfd01c4087672cd3 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 10 Jan 2025 22:15:58 +0100 Subject: [PATCH 30/43] Update MC version in artifact name --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6f142013..1e09fde7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -125,7 +125,7 @@ tasks.withType { options.encoding = "UTF-8" options.setIncremental(true) options.compilerArgs.add("-parameters") - options.release = 17 + options.release = 21 } tasks { @@ -138,7 +138,7 @@ tasks { } shadowJar { - archiveFileName.set("ParcelLockers v${project.version} (MC 1.17.x-1.21.x).jar") + archiveFileName.set("ParcelLockers v${project.version} (MC 1.21.3-1.21.4).jar") exclude( "org/intellij/lang/annotations/**", From e62bcd6df5a085fd85abc4a1f1104b7df4bfcae0 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 14 Jan 2025 19:05:47 +0100 Subject: [PATCH 31/43] Apply Rollczi's suggestions --- .../content/repository/ParcelContentRepository.java | 2 -- .../repository/ParcelContentRepositoryOrmLite.java | 6 ------ .../content/repository/ParcelContentWrapper.java | 2 +- .../database/persister/ItemStackPersister.java | 10 +--------- .../database/persister/PositionPersister.java | 11 +---------- .../locker/repository/LockerRepositoryOrmLite.java | 3 ++- .../locker/repository/LockerWrapper.java | 2 +- .../parcel/repository/ParcelRepository.java | 2 +- .../parcel/repository/ParcelRepositoryOrmLite.java | 3 +-- .../parcel/repository/ParcelWrapper.java | 4 ++-- .../parcellockers/user/repository/UserWrapper.java | 2 +- 11 files changed, 11 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java index 54cf3389..cc7a9e0d 100644 --- a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java @@ -12,8 +12,6 @@ public interface ParcelContentRepository { CompletableFuture remove(UUID uniqueId); - CompletableFuture update(ParcelContent parcelContent); - CompletableFuture> find(UUID uniqueId); } diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java index 511622db..a565af0b 100644 --- a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java @@ -25,7 +25,6 @@ public ParcelContentRepositoryOrmLite(DatabaseManager databaseManager, Scheduler } } - @Override public CompletableFuture save(ParcelContent parcelContent) { return this.saveIfNotExist(ParcelContentWrapper.class, ParcelContentWrapper.from(parcelContent)).thenApply(dao -> null); @@ -36,11 +35,6 @@ public CompletableFuture remove(UUID uniqueId) { return this.deleteById(ParcelContentWrapper.class, uniqueId); } - @Override - public CompletableFuture update(ParcelContent parcelContent) { - return this.save(ParcelContentWrapper.class, ParcelContentWrapper.from(parcelContent)).thenApply(dao -> null); - } - @Override public CompletableFuture> find(UUID uniqueId) { return this.select(ParcelContentWrapper.class, uniqueId).thenApply(parcelContentWrapper -> Optional.ofNullable(parcelContentWrapper.toParcelContent())); diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java index f8c9e943..8bc070ba 100644 --- a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java +++ b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java @@ -10,7 +10,7 @@ import java.util.UUID; @DatabaseTable(tableName = "parcel_content") -public class ParcelContentWrapper { +class ParcelContentWrapper { @DatabaseField(id = true) private UUID uniqueId; diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java index 5c238d8b..8cf486e2 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java @@ -35,10 +35,6 @@ public static ItemStackPersister getSingleton() { @Override public Object javaToSqlArg(FieldType fieldType, Object javaObject) { - if (javaObject == null) { - return null; - } - List stacks = (List) javaObject; try { @@ -52,7 +48,7 @@ public Object javaToSqlArg(FieldType fieldType, Object javaObject) { @Override public Object parseDefaultString(FieldType fieldType, String defaultString) { - return String.valueOf(defaultString); + return defaultString; } @Override @@ -64,10 +60,6 @@ public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int c public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) { String string = (String) sqlArg; - if (string == null) { - return null; - } - try { return JSON.readValue(string, JSON.getTypeFactory().constructCollectionType(List.class, ItemStack.class)); } diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java index de9ba17f..054912ce 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java @@ -22,10 +22,6 @@ public static PositionPersister getSingleton() { @Override public Object javaToSqlArg(FieldType fieldType, Object javaObject) { - if (javaObject == null) { - return null; - } - Position pos = (Position) javaObject; String worldName = "world"; @@ -45,17 +41,12 @@ public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int c @Override public Object parseDefaultString(FieldType fieldType, String defaultStr) { - return String.valueOf(defaultStr); + return defaultStr; } @Override public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) { String s = (String) sqlArg; - - if (s == null) { - return null; - } - String[] params = s.split("/"); return new Position( diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java index 7f307381..680c2c7d 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -32,6 +32,7 @@ public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler schedu } catch (SQLException ex) { Sentry.captureException(ex); ex.printStackTrace(); + throw new RuntimeException("Failed to initialize locker table", ex); } } @@ -60,7 +61,7 @@ public CompletableFuture> findByPosition(Position position) { // We have to assume that there is only one locker per position return this.action(LockerWrapper.class, dao -> { List lockers = dao.queryForEq("position", position); - return lockers.isEmpty() ? Optional.empty() : Optional.of(lockers.get(0).toLocker()); + return lockers.isEmpty() ? Optional.empty() : Optional.of(lockers.getFirst().toLocker()); }); } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java index 3682d80b..76009211 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java @@ -17,7 +17,7 @@ class LockerWrapper { @DatabaseField(columnName = "description") private String description; - @DatabaseField(columnName = "position", persisterClass = PositionPersister.class, unique = true) + @DatabaseField(columnName = "position", persisterClass = PositionPersister.class, unique = true, index = true) private Position position; LockerWrapper() { diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java index 1a382ec4..0f7a7da1 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java @@ -27,6 +27,6 @@ public interface ParcelRepository { Map cache(); - Optional findParcel(UUID uuid); + Optional findParcelFromCache(UUID uuid); } diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index 77cbb34d..b7d4f4d2 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -112,8 +112,7 @@ private void removeFromCache(UUID uuid) { this.cache.remove(uuid); } - @Override - public Optional findParcel(UUID uuid) { + public Optional findParcelFromCache(UUID uuid) { return Optional.ofNullable(this.cache.get(uuid)); } } diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java index 531a0735..2b42ff11 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java @@ -14,7 +14,7 @@ class ParcelWrapper { @DatabaseField(id = true, columnName = "uuid") private UUID uuid; - @DatabaseField(columnName = "sender") + @DatabaseField(columnName = "sender", index = true) private UUID sender; @DatabaseField(columnName = "name") @@ -26,7 +26,7 @@ class ParcelWrapper { @DatabaseField(columnName = "priority") private boolean priority; - @DatabaseField(columnName = "receiver") + @DatabaseField(columnName = "receiver", index = true) private UUID receiver; @DatabaseField(columnName = "size") diff --git a/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java b/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java index 7c1733b2..de539514 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java +++ b/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java @@ -12,7 +12,7 @@ class UserWrapper { @DatabaseField(id = true) private UUID uuid; - @DatabaseField + @DatabaseField(index = true) private String username; UserWrapper() { From 441acd6512d3bfea72969e308adfd6846a432ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 14 Jan 2025 19:06:45 +0100 Subject: [PATCH 32/43] Update src/test/java/com/eternalcode/parcellockers/TestScheduler.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../java/com/eternalcode/parcellockers/TestScheduler.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/com/eternalcode/parcellockers/TestScheduler.java b/src/test/java/com/eternalcode/parcellockers/TestScheduler.java index f4c0a1e9..1a3fd3e9 100644 --- a/src/test/java/com/eternalcode/parcellockers/TestScheduler.java +++ b/src/test/java/com/eternalcode/parcellockers/TestScheduler.java @@ -14,6 +14,10 @@ public class TestScheduler implements Scheduler { private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(8); + + public void shutdown() { + executorService.shutdown(); + } @Override public Task run(Runnable runnable) { From ca5922e8b3ba1db1b8aaf0550a817306c460cce8 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Tue, 14 Jan 2025 21:26:47 +0100 Subject: [PATCH 33/43] Refactor caching system --- .../parcellockers/ParcelLockers.java | 25 ++++---- .../argument/ParcelLockerArgument.java | 30 +++++----- .../controller/LockerBreakController.java | 38 +++++++------ .../LockerInteractionController.java | 10 ++-- .../locker/repository/LockerCache.java | 57 +++++++++++++++++++ .../locker/repository/LockerRepository.java | 11 ---- .../repository/LockerRepositoryOrmLite.java | 54 +++--------------- .../command/argument/ParcelArgument.java | 22 +++---- .../parcel/repository/ParcelCache.java | 38 +++++++++++++ .../parcel/repository/ParcelRepository.java | 8 +-- .../repository/ParcelRepositoryOrmLite.java | 37 ++++++------ 11 files changed, 187 insertions(+), 143 deletions(-) rename src/main/java/com/eternalcode/parcellockers/{parcel/command => locker}/argument/ParcelLockerArgument.java (73%) create mode 100644 src/main/java/com/eternalcode/parcellockers/locker/repository/LockerCache.java create mode 100644 src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelCache.java diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index e9e258d3..64ac0475 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -17,17 +17,18 @@ import com.eternalcode.parcellockers.itemstorage.repository.ItemStorageRepository; import com.eternalcode.parcellockers.itemstorage.repository.ItemStorageRepositoryOrmLite; import com.eternalcode.parcellockers.locker.Locker; +import com.eternalcode.parcellockers.locker.argument.ParcelLockerArgument; import com.eternalcode.parcellockers.locker.controller.LockerBreakController; import com.eternalcode.parcellockers.locker.controller.LockerInteractionController; import com.eternalcode.parcellockers.locker.controller.LockerPlaceController; +import com.eternalcode.parcellockers.locker.repository.LockerCache; import com.eternalcode.parcellockers.locker.repository.LockerRepositoryOrmLite; import com.eternalcode.parcellockers.notification.NotificationAnnouncer; import com.eternalcode.parcellockers.parcel.Parcel; import com.eternalcode.parcellockers.parcel.ParcelManager; import com.eternalcode.parcellockers.parcel.command.ParcelCommand; import com.eternalcode.parcellockers.parcel.command.argument.ParcelArgument; -import com.eternalcode.parcellockers.parcel.command.argument.ParcelLockerArgument; -import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; +import com.eternalcode.parcellockers.parcel.repository.ParcelCache; import com.eternalcode.parcellockers.parcel.repository.ParcelRepositoryOrmLite; import com.eternalcode.parcellockers.updater.UpdaterService; import com.eternalcode.parcellockers.user.LoadUserController; @@ -128,15 +129,19 @@ public void onEnable() { .threadPool(20) .build(); - LockerRepositoryOrmLite lockerRepository = new LockerRepositoryOrmLite(databaseManager, scheduler); - lockerRepository.updateCaches(); + LockerCache lockerCache = new LockerCache(); + ParcelCache parcelCache = new ParcelCache(); - ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryOrmLite(databaseManager, scheduler); + LockerRepositoryOrmLite lockerRepository = new LockerRepositoryOrmLite(databaseManager, scheduler, lockerCache); + lockerRepository.updateCaches(); - ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager, scheduler); + ParcelRepositoryOrmLite parcelRepository = new ParcelRepositoryOrmLite(databaseManager, scheduler, parcelCache); + parcelRepository.updateCaches(); ParcelManager parcelManager = new ParcelManager(config, announcer, parcelRepository); + ItemStorageRepository itemStorageRepository = new ItemStorageRepositoryOrmLite(databaseManager, scheduler); + UserRepository userRepository = new UserRepositoryOrmLite(databaseManager, scheduler); UserManager userManager = new UserManager(userRepository); @@ -146,8 +151,8 @@ public void onEnable() { ParcelListGUI parcelListGUI = new ParcelListGUI(this, server, miniMessage, config, parcelRepository, lockerRepository, userManager, mainGUI); this.liteCommands = LiteBukkitFactory.builder("parcellockers", this) - .argument(Parcel.class, new ParcelArgument(parcelRepository)) - .argument(Locker.class, new ParcelLockerArgument(lockerRepository)) + .argument(Parcel.class, new ParcelArgument(parcelCache)) + .argument(Locker.class, new ParcelLockerArgument(lockerCache)) .extension(new LiteAdventureExtension<>()) .message(LiteBukkitMessages.PLAYER_ONLY, config.messages.onlyForPlayers) .commands(LiteCommandsAnnotations.of( @@ -167,9 +172,9 @@ public void onEnable() { LockerMainGUI lockerMainGUI = new LockerMainGUI(this, miniMessage, config, itemStorageRepository, parcelRepository, lockerRepository, announcer, parcelContentRepository, userRepository, this.skullAPI); Stream.of( - new LockerInteractionController(lockerRepository, lockerMainGUI), + new LockerInteractionController(lockerCache, lockerMainGUI), new LockerPlaceController(config, this, lockerRepository, announcer), - new LockerBreakController(lockerRepository, announcer, config.messages), + new LockerBreakController(lockerRepository, lockerCache, announcer, config.messages), new PrepareUserController(userManager), new LoadUserController(userManager, server) ).forEach(controller -> server.getPluginManager().registerEvents(controller, this)); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelLockerArgument.java b/src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java similarity index 73% rename from src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelLockerArgument.java rename to src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java index f1e0905d..77224d15 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelLockerArgument.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java @@ -1,7 +1,7 @@ -package com.eternalcode.parcellockers.parcel.command.argument; +package com.eternalcode.parcellockers.locker.argument; import com.eternalcode.parcellockers.locker.Locker; -import com.eternalcode.parcellockers.locker.repository.LockerRepository; +import com.eternalcode.parcellockers.locker.repository.LockerCache; import dev.rollczi.litecommands.argument.Argument; import dev.rollczi.litecommands.argument.parser.ParseResult; import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; @@ -12,27 +12,27 @@ public class ParcelLockerArgument extends ArgumentResolver { - private final LockerRepository lockerRepository; + private final LockerCache cache; - public ParcelLockerArgument(LockerRepository lockerRepository) { - this.lockerRepository = lockerRepository; - } - - @Override - public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { - return this.lockerRepository.cache() - .values() - .stream() - .map(Locker::description) - .collect(SuggestionResult.collector()); + public ParcelLockerArgument(LockerCache cache) { + this.cache = cache; } @Override protected ParseResult parse(Invocation invocation, Argument argument, String s) { - return ParseResult.success(this.lockerRepository.cache().values() + return ParseResult.success(this.cache.cache().values() .stream() .filter(locker -> locker.description().equalsIgnoreCase(s)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("Locker with description '" + s + "' not found"))); } + + @Override + public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { + return this.cache.cache() + .values() + .stream() + .map(Locker::description) + .collect(SuggestionResult.collector()); + } } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java index b643bfc1..ec0228e9 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java @@ -1,6 +1,7 @@ package com.eternalcode.parcellockers.locker.controller; import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; +import com.eternalcode.parcellockers.locker.repository.LockerCache; import com.eternalcode.parcellockers.locker.repository.LockerRepository; import com.eternalcode.parcellockers.notification.NotificationAnnouncer; import com.eternalcode.parcellockers.shared.Position; @@ -24,11 +25,13 @@ public class LockerBreakController implements Listener { private final LockerRepository lockerRepository; + private final LockerCache cache; private final NotificationAnnouncer announcer; private final PluginConfiguration.Messages messages; - public LockerBreakController(LockerRepository lockerRepository, NotificationAnnouncer announcer, PluginConfiguration.Messages messages) { + public LockerBreakController(LockerRepository lockerRepository, LockerCache cache, NotificationAnnouncer announcer, PluginConfiguration.Messages messages) { this.lockerRepository = lockerRepository; + this.cache = cache; this.announcer = announcer; this.messages = messages; } @@ -40,23 +43,22 @@ public void onBlockBreak(BlockBreakEvent event) { Position position = PositionAdapter.convert(location); Player player = event.getPlayer(); - this.lockerRepository.findByPosition(position).whenComplete((locker, throwable) -> { - if (locker.isEmpty()) { - return; - } + if (this.cache.get(position).isEmpty()) { + return; + } - if (throwable != null) { - throwable.printStackTrace(); - return; - } + if (!player.hasPermission("parcellockers.admin.break")) { + event.setCancelled(true); + this.announcer.sendMessage(player, this.messages.cannotBreakParcelLocker); + return; + } - if (!player.hasPermission("parcellockers.admin.break")) { - event.setCancelled(true); - this.announcer.sendMessage(player, this.messages.cannotBreakParcelLocker); + this.lockerRepository.findByPosition(position).thenAccept((locker) -> { + if (locker.isEmpty()) { return; } - UUID toRemove = this.lockerRepository.positionCache().get(position); + UUID toRemove = this.cache.get(position).get().uuid(); this.lockerRepository.remove(toRemove); this.announcer.sendMessage(player, this.messages.parcelLockerSuccessfullyDeleted); @@ -78,7 +80,7 @@ public void onBlockBurn(BlockBurnEvent event) { Location location = block.getLocation(); Position position = PositionAdapter.convert(location); - if (this.lockerRepository.isInCache(position)) { + if (this.cache.get(position).isPresent()) { event.setCancelled(true); } } @@ -89,7 +91,7 @@ public void onBlockExplode(BlockExplodeEvent event) { Location location = block.getLocation(); Position position = PositionAdapter.convert(location); - if (this.lockerRepository.isInCache(position)) { + if (this.cache.get(position).isPresent()) { event.setCancelled(true); } } @@ -99,7 +101,7 @@ public void onEntityExplode(EntityExplodeEvent event) { event.blockList().removeIf(block -> { Location location = block.getLocation(); Position position = PositionAdapter.convert(location); - return this.lockerRepository.isInCache(position); + return this.cache.get(position).isPresent(); }); } @@ -109,7 +111,7 @@ public void onBlockIgnite(BlockIgniteEvent event) { Location location = block.getLocation(); Position position = PositionAdapter.convert(location); - if (this.lockerRepository.isInCache(position)) { + if (this.cache.get(position).isPresent()) { event.setCancelled(true); } } @@ -120,7 +122,7 @@ public void onBlockDamage(BlockDamageEvent event) { Location location = block.getLocation(); Position position = PositionAdapter.convert(location); - if (this.lockerRepository.isInCache(position)) { + if (this.cache.get(position).isPresent()) { event.setCancelled(true); } } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerInteractionController.java b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerInteractionController.java index f35afdf7..8a1eb83c 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerInteractionController.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerInteractionController.java @@ -1,7 +1,7 @@ package com.eternalcode.parcellockers.locker.controller; import com.eternalcode.parcellockers.gui.implementation.locker.LockerMainGUI; -import com.eternalcode.parcellockers.locker.repository.LockerRepository; +import com.eternalcode.parcellockers.locker.repository.LockerCache; import com.eternalcode.parcellockers.shared.Position; import com.eternalcode.parcellockers.shared.PositionAdapter; import org.bukkit.Material; @@ -15,11 +15,11 @@ public class LockerInteractionController implements Listener { - private final LockerRepository parcelLockerRepository; + private final LockerCache cache; private final LockerMainGUI lockerMainGUI; - public LockerInteractionController(LockerRepository parcelLockerRepository, LockerMainGUI lockerMainGUI) { - this.parcelLockerRepository = parcelLockerRepository; + public LockerInteractionController(LockerCache cache, LockerMainGUI lockerMainGUI) { + this.cache = cache; this.lockerMainGUI = lockerMainGUI; } @@ -36,7 +36,7 @@ public void onInventoryOpen(PlayerInteractEvent event) { return; } - if (this.parcelLockerRepository.isInCache(blockPos)) { + if (this.cache.get(blockPos).isPresent()) { event.setCancelled(true); this.lockerMainGUI.show(player); } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerCache.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerCache.java new file mode 100644 index 00000000..3bd43984 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerCache.java @@ -0,0 +1,57 @@ +package com.eternalcode.parcellockers.locker.repository; + +import com.eternalcode.parcellockers.locker.Locker; +import com.eternalcode.parcellockers.shared.Position; + +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class LockerCache { + + private final Map cache = new ConcurrentHashMap<>(); + private final Map positionCache = new ConcurrentHashMap<>(); + + public void put(Locker locker) { + this.cache.put(locker.uuid(), locker); + this.positionCache.put(locker.position(), locker); + } + + public void putAll(Map lockers) { + this.cache.putAll(lockers); + lockers.values().forEach(locker -> this.positionCache.put(locker.position(), locker)); + } + + public Locker remove(UUID uuid) { + this.positionCache.remove(this.cache.get(uuid).position()); + return this.cache.remove(uuid); + } + + public Locker remove(Locker locker) { + this.positionCache.remove(locker.position()); + return this.cache.remove(locker.uuid()); + } + + public Map cache() { + return Collections.unmodifiableMap(this.cache); + } + + public Map positionCache() { + return Collections.unmodifiableMap(this.positionCache); + } + + public Optional get(UUID uuid) { + return Optional.ofNullable(this.cache.get(uuid)); + } + + public Optional get(Position position) { + return Optional.ofNullable(this.positionCache.get(position)); + } + + public void clear() { + this.cache.clear(); + this.positionCache.clear(); + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java index 0d28d782..2071ab73 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java @@ -5,7 +5,6 @@ import com.eternalcode.parcellockers.shared.Position; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -25,14 +24,4 @@ public interface LockerRepository { CompletableFuture remove(Locker locker); CompletableFuture findPage(Page page); - - Optional getFromCache(UUID uuid); - - Map cache(); - - Map positionCache(); - - boolean isInCache(Position position); - - boolean isInCache(UUID uuid); } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java index 680c2c7d..a088a1a6 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java @@ -10,7 +10,6 @@ import io.sentry.Sentry; import java.sql.SQLException; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -21,11 +20,11 @@ public class LockerRepositoryOrmLite extends AbstractRepositoryOrmLite implements LockerRepository { - private final Map cache = new ConcurrentHashMap<>(); - private final Map positionCache = new ConcurrentHashMap<>(); + private final LockerCache cache; - public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler, LockerCache cache) { super(databaseManager, scheduler); + this.cache = cache; try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), LockerWrapper.class); @@ -39,7 +38,7 @@ public LockerRepositoryOrmLite(DatabaseManager databaseManager, Scheduler schedu @Override public CompletableFuture save(Locker locker) { return this.save(LockerWrapper.class, LockerWrapper.from(locker)).thenApply(dao -> { - this.addToCache(locker); + this.cache.put(locker); return null; }); } @@ -70,10 +69,7 @@ public CompletableFuture remove(UUID uuid) { return this.deleteById(LockerWrapper.class, uuid) .thenApply(result -> { if (result > 0) { - Locker locker = this.cache.remove(uuid); - if (locker != null) { - this.positionCache.remove(locker.position()); - } + this.cache.remove(uuid); } return result; }); @@ -96,55 +92,19 @@ public CompletableFuture findPage(Page page) { boolean hasNext = lockers.size() > page.getLimit(); if (hasNext) { - lockers.remove(lockers.size() - 1); + lockers.removeLast(); } return new LockerPageResult(lockers, hasNext); }); } - @Override - public Optional getFromCache(UUID uuid) { - return Optional.ofNullable(this.cache.get(uuid)); - } - - @Override - public Map cache() { - return Collections.unmodifiableMap(this.cache); - } - - @Override - public Map positionCache() { - return Collections.unmodifiableMap(this.positionCache); - } - - @Override - public boolean isInCache(Position position) { - return this.positionCache.containsKey(position); - } - - @Override - public boolean isInCache(UUID uuid) { - return this.cache.containsKey(uuid); - } - public void updateCaches() { this.findAll().thenAccept(lockers -> { Map newCache = new ConcurrentHashMap<>(); - Map newPositionCache = new ConcurrentHashMap<>(); - lockers.forEach(locker -> { - newCache.put(locker.uuid(), locker); - newPositionCache.put(locker.position(), locker.uuid()); - }); + lockers.forEach(locker -> newCache.put(locker.uuid(), locker)); this.cache.clear(); - this.positionCache.clear(); this.cache.putAll(newCache); - this.positionCache.putAll(newPositionCache); }); } - - private void addToCache(Locker locker) { - this.cache.put(locker.uuid(), locker); - this.positionCache.put(locker.position(), locker.uuid()); - } } diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java b/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java index 69fc0604..0c55ae99 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java @@ -1,7 +1,7 @@ package com.eternalcode.parcellockers.parcel.command.argument; import com.eternalcode.parcellockers.parcel.Parcel; -import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; +import com.eternalcode.parcellockers.parcel.repository.ParcelCache; import dev.rollczi.litecommands.argument.Argument; import dev.rollczi.litecommands.argument.parser.ParseResult; import dev.rollczi.litecommands.argument.resolver.ArgumentResolver; @@ -11,34 +11,30 @@ import dev.rollczi.litecommands.suggestion.SuggestionResult; import org.bukkit.command.CommandSender; +import java.util.Optional; import java.util.UUID; -import java.util.concurrent.CompletableFuture; public class ParcelArgument extends ArgumentResolver { - private final ParcelRepository databaseService; + private final ParcelCache cache; - public ParcelArgument(ParcelRepository cache) { - this.databaseService = cache; + public ParcelArgument(ParcelCache cache) { + this.cache = cache; } @Override protected ParseResult parse(Invocation invocation, Argument context, String argument) { UUID parcelId = UUID.fromString(argument); - CompletableFuture> future = this.databaseService.findByUUID(parcelId) - .thenApply(optional -> optional - .map(ParseResult::success) - .orElse(ParseResult.failure(InvalidUsage.Cause.INVALID_ARGUMENT))); - return ParseResult.completableFuture(future); + Optional parcel = this.cache.get(parcelId); + return parcel.map(ParseResult::success) + .orElseGet(() -> ParseResult.failure(InvalidUsage.Cause.INVALID_ARGUMENT)); } @Override public SuggestionResult suggest(Invocation invocation, Argument argument, SuggestionContext context) { - return this.databaseService.cache().values().stream() + return this.cache.cache().values().stream() .map(Parcel::uuid) .map(UUID::toString) .collect(SuggestionResult.collector()); - - } } diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelCache.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelCache.java new file mode 100644 index 00000000..dffcd833 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelCache.java @@ -0,0 +1,38 @@ +package com.eternalcode.parcellockers.parcel.repository; + +import com.eternalcode.parcellockers.parcel.Parcel; + +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class ParcelCache { + + private final Map cache = new ConcurrentHashMap<>(); + + public void put(Parcel parcel) { + cache.put(parcel.uuid(), parcel); + } + + public void putAll(Map parcels) { + cache.putAll(parcels); + } + + public Optional get(UUID uuid) { + return Optional.ofNullable(cache.get(uuid)); + } + + public void remove(UUID uuid) { + cache.remove(uuid); + } + + public void clear() { + cache.clear(); + } + + public Map cache() { + return Collections.unmodifiableMap(cache); + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java index 0f7a7da1..e57b2935 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java @@ -4,7 +4,6 @@ import com.eternalcode.parcellockers.shared.Page; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -13,6 +12,8 @@ public interface ParcelRepository { CompletableFuture save(Parcel parcel); + CompletableFuture>> findAll(); + CompletableFuture> findByUUID(UUID uuid); CompletableFuture>> findBySender(UUID sender); @@ -24,9 +25,4 @@ public interface ParcelRepository { CompletableFuture remove(UUID uuid); CompletableFuture findPage(Page page); - - Map cache(); - - Optional findParcelFromCache(UUID uuid); - } diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index b7d4f4d2..cdc37744 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -9,7 +9,6 @@ import io.sentry.Sentry; import java.sql.SQLException; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -23,10 +22,11 @@ public class ParcelRepositoryOrmLite extends AbstractRepositoryOrmLite implement private static final String RECEIVER_COLUMN = "receiver"; private static final String SENDER_COLUMN = "sender"; - private final Map cache = new ConcurrentHashMap<>(); + private final ParcelCache cache; - public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { + public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler, ParcelCache cache) { super(databaseManager, scheduler); + this.cache = cache; try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ParcelWrapper.class); @@ -39,7 +39,7 @@ public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler schedu @Override public CompletableFuture save(Parcel parcel) { return this.save(ParcelWrapper.class, ParcelWrapper.from(parcel)).thenApply(dao -> { - this.addToCache(parcel); + this.cache.put(parcel); return null; }); } @@ -75,7 +75,7 @@ public CompletableFuture remove(UUID uuid) { CompletableFuture removeFuture = this.deleteById(ParcelWrapper.class, uuid); removeFuture.thenAccept(deletedCount -> { if (deletedCount > 0) { - this.removeFromCache(uuid); + this.cache.remove(uuid); } }); return removeFuture; @@ -84,7 +84,7 @@ public CompletableFuture remove(UUID uuid) { @Override public CompletableFuture findPage(Page page) { return this.action(ParcelWrapper.class, dao -> { - List parcels = dao.queryBuilder() + List parcels = dao.queryBuilder() .limit((long) page.getLimit() + 1) .offset((long) page.getOffset()) .query() @@ -93,26 +93,27 @@ public CompletableFuture findPage(Page page) { boolean hasNext = parcels.size() > page.getLimit(); if (hasNext) { - parcels.remove(parcels.size() - 1); + parcels.removeLast(); } return new ParcelPageResult(parcels, hasNext); }); } @Override - public Map cache() { - return Collections.unmodifiableMap(this.cache); - } - - private void addToCache(Parcel parcel) { - this.cache.put(parcel.uuid(), parcel); + public CompletableFuture>> findAll() { + return this.selectAll(ParcelWrapper.class).thenApply(parcels -> Optional.of(parcels.stream() + .map(ParcelWrapper::toParcel) + .toList())); } - private void removeFromCache(UUID uuid) { - this.cache.remove(uuid); - } + public void updateCaches() { + this.findAll().thenAccept(parcels -> { + List parcelList = parcels.orElse(List.of()); + Map newCache = new ConcurrentHashMap<>(); - public Optional findParcelFromCache(UUID uuid) { - return Optional.ofNullable(this.cache.get(uuid)); + parcelList.forEach(parcel -> newCache.put(parcel.uuid(), parcel)); + this.cache.clear(); + this.cache.putAll(newCache); + }); } } From d62297e78dfcd72405b11a34fa0acb637b0e864a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:45:50 +0100 Subject: [PATCH 34/43] Update src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com> --- .../parcellockers/parcel/repository/ParcelWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java index 2b42ff11..4e78b019 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java @@ -11,7 +11,7 @@ @DatabaseTable(tableName = "parcels") class ParcelWrapper { - @DatabaseField(id = true, columnName = "uuid") + @DatabaseField(columnName = "uuid", id = true) private UUID uuid; @DatabaseField(columnName = "sender", index = true) From b7be250930090967b816e54c43c722d96f01ec69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:48:39 +0100 Subject: [PATCH 35/43] Update src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../parcellockers/parcel/repository/ParcelWrapper.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java index 4e78b019..99a2ffe6 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java @@ -32,12 +32,11 @@ class ParcelWrapper { @DatabaseField(columnName = "size") private ParcelSize size; - @DatabaseField(columnName = "entryLocker") + @DatabaseField(columnName = "entryLocker", index = true) private UUID entryLocker; - @DatabaseField(columnName = "destinationLocker") + @DatabaseField(columnName = "destinationLocker", index = true) private UUID destinationLocker; - ParcelWrapper() { } From ecd70af518bc480be47385086080253e22b5ee80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:48:56 +0100 Subject: [PATCH 36/43] Update src/main/java/com/eternalcode/parcellockers/ParcelLockers.java Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com> --- src/main/java/com/eternalcode/parcellockers/ParcelLockers.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index 64ac0475..e7a7ed70 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -121,7 +121,6 @@ public void onEnable() { this.getLogger().severe("Could not connect to database! Some functions may not work properly!"); throw new RuntimeException(exception); } - this.databaseManager = databaseManager; this.skullAPI = LiteSkullFactory.builder() .cacheExpireAfterWrite(Duration.ofMinutes(45L)) From 90b5f11727ff04684df49a6709eca765e88c15a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:51:52 +0100 Subject: [PATCH 37/43] Update src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../parcellockers/database/persister/PositionPersister.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java index 054912ce..2e8383ff 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java @@ -10,7 +10,7 @@ public class PositionPersister extends BaseDataType { - private static final PositionPersister instance = new PositionPersister(); + private static final PositionPersister INSTANCE = new PositionPersister(); private PositionPersister() { super(SqlType.LONG_STRING, new Class[] { PositionPersister.class }); From 1eef1e49f304093d9233a6b0c007bd353dca44d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:52:40 +0100 Subject: [PATCH 38/43] Update src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../database/persister/PositionPersister.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java index 2e8383ff..0f31547e 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java @@ -48,13 +48,19 @@ public Object parseDefaultString(FieldType fieldType, String defaultStr) { public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) { String s = (String) sqlArg; String[] params = s.split("/"); - - return new Position( - Integer.parseInt(params[1]), - Integer.parseInt(params[2]), - Integer.parseInt(params[3]), - params[0] - ); + if (params.length != 4) { + throw new IllegalArgumentException("Invalid position format: " + s); + } + try { + return new Position( + Integer.parseInt(params[1]), + Integer.parseInt(params[2]), + Integer.parseInt(params[3]), + params[0] + ); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid coordinate format: " + s, e); + } } } From cee39bc69fb6ae9f458634d80a06f8889f1acf31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:53:31 +0100 Subject: [PATCH 39/43] Update src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../content/repository/ParcelContentRepositoryOrmLite.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java index a565af0b..a2198e7b 100644 --- a/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java @@ -21,7 +21,7 @@ public ParcelContentRepositoryOrmLite(DatabaseManager databaseManager, Scheduler TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ParcelContentWrapper.class); } catch (SQLException exception) { Sentry.captureException(exception); - exception.printStackTrace(); + throw new RuntimeException("Failed to create ParcelContent table", exception); } } From 025a95bb9b4619b00591c3f3b38a8dd4fc2859f6 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:14:37 +0100 Subject: [PATCH 40/43] Apply CodeRabbit suggestions --- .../locker/argument/ParcelLockerArgument.java | 5 +++-- .../parcel/command/argument/ParcelArgument.java | 12 ++++++++---- .../parcellockers/user/repository/UserWrapper.java | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java b/src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java index 77224d15..13a0281e 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java @@ -20,11 +20,12 @@ public ParcelLockerArgument(LockerCache cache) { @Override protected ParseResult parse(Invocation invocation, Argument argument, String s) { - return ParseResult.success(this.cache.cache().values() + return this.cache.cache().values() .stream() .filter(locker -> locker.description().equalsIgnoreCase(s)) .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Locker with description '" + s + "' not found"))); + .map(ParseResult::success) + .orElseThrow(() -> new IllegalArgumentException("Locker with description '" + s + "' not found")); } @Override diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java b/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java index 0c55ae99..2f416ee4 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java @@ -24,10 +24,14 @@ public ParcelArgument(ParcelCache cache) { @Override protected ParseResult parse(Invocation invocation, Argument context, String argument) { - UUID parcelId = UUID.fromString(argument); - Optional parcel = this.cache.get(parcelId); - return parcel.map(ParseResult::success) - .orElseGet(() -> ParseResult.failure(InvalidUsage.Cause.INVALID_ARGUMENT)); + try { + UUID parcelId = UUID.fromString(argument); + Optional parcel = this.cache.get(parcelId); + return parcel.map(ParseResult::success) + .orElseGet(() -> ParseResult.failure(InvalidUsage.Cause.INVALID_ARGUMENT)); + } catch (IllegalArgumentException e) { + return ParseResult.failure(InvalidUsage.Cause.INVALID_ARGUMENT); + } } @Override diff --git a/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java b/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java index de539514..46a4a764 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java +++ b/src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java @@ -12,7 +12,7 @@ class UserWrapper { @DatabaseField(id = true) private UUID uuid; - @DatabaseField(index = true) + @DatabaseField(index = true, unique = true, canBeNull = false) private String username; UserWrapper() { From defdc124cd63cbb3291e1e5e51ae98cec786ef18 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:22:11 +0100 Subject: [PATCH 41/43] Fix build --- .../database/persister/PositionPersister.java | 2 +- .../ParcelDatabaseServiceIntegrationTest.java | 4 +++- ...lLockerDatabaseServiceIntegrationTest.java | 22 ++++++++++++++++--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java index 0f31547e..2e4208d1 100644 --- a/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java +++ b/src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java @@ -17,7 +17,7 @@ private PositionPersister() { } public static PositionPersister getSingleton() { - return instance; + return INSTANCE; } @Override diff --git a/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java b/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java index 0c0bd269..b6cca56a 100644 --- a/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java +++ b/src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java @@ -5,6 +5,7 @@ import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; import com.eternalcode.parcellockers.parcel.Parcel; import com.eternalcode.parcellockers.parcel.ParcelSize; +import com.eternalcode.parcellockers.parcel.repository.ParcelCache; import com.eternalcode.parcellockers.parcel.repository.ParcelPageResult; import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; import com.eternalcode.parcellockers.parcel.repository.ParcelRepositoryOrmLite; @@ -37,8 +38,9 @@ void test() { File dataFolder = new File("run/plugins/ParcelLockers"); PluginConfiguration config = new ConfigurationManager(dataFolder).load(new PluginConfiguration()); DatabaseManager databaseManager = new DatabaseManager(config, Logger.getLogger("ParcelLockers"), dataFolder); + ParcelCache cache = new ParcelCache(); - ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager, new TestScheduler()); + ParcelRepository parcelRepository = new ParcelRepositoryOrmLite(databaseManager, new TestScheduler(), cache); UUID uuid = UUID.randomUUID(); UUID sender = UUID.randomUUID(); UUID receiver = UUID.randomUUID(); diff --git a/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java b/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java index 5c88662e..da7d3cc5 100644 --- a/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java +++ b/src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java @@ -4,18 +4,22 @@ import com.eternalcode.parcellockers.configuration.ConfigurationManager; import com.eternalcode.parcellockers.configuration.implementation.PluginConfiguration; import com.eternalcode.parcellockers.locker.Locker; +import com.eternalcode.parcellockers.locker.repository.LockerCache; import com.eternalcode.parcellockers.locker.repository.LockerPageResult; import com.eternalcode.parcellockers.locker.repository.LockerRepository; import com.eternalcode.parcellockers.locker.repository.LockerRepositoryOrmLite; import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.shared.Position; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.utility.DockerImageName; import java.io.File; +import java.nio.file.Path; import java.util.Optional; import java.util.UUID; import java.util.logging.Logger; @@ -29,13 +33,20 @@ class ParcelLockerDatabaseServiceIntegrationTest extends ParcelLockerIntegration @Container private static final MySQLContainer mySQLContainer = new MySQLContainer(DockerImageName.parse("mysql:latest")); + @TempDir + private Path tempDir; + + private DatabaseManager databaseManager; + @Test void test() { - File dataFolder = new File("run/plugins/ParcelLockers"); + File dataFolder = tempDir.resolve("ParcelLockers").toFile(); PluginConfiguration config = new ConfigurationManager(dataFolder).load(new PluginConfiguration()); DatabaseManager databaseManager = new DatabaseManager(config, Logger.getLogger("ParcelLockers"), dataFolder); + this.databaseManager = databaseManager; + LockerCache cache = new LockerCache(); - LockerRepository parcelLockerRepository = new LockerRepositoryOrmLite(databaseManager, new TestScheduler()); + LockerRepository parcelLockerRepository = new LockerRepositoryOrmLite(databaseManager, new TestScheduler(), cache); UUID uuid = UUID.randomUUID(); String description = "Parcel locker description."; @@ -54,10 +65,15 @@ void test() { LockerPageResult pageResult = await(parcelLockerRepository.findPage(new Page(0, 28))); assertEquals(1, pageResult.lockers().size()); - assertEquals(uuid, pageResult.lockers().iterator().next().uuid()); + assertEquals(uuid, pageResult.lockers().getFirst().uuid()); await(parcelLockerRepository.remove(uuid)); Optional removed = await(parcelLockerRepository.findByUUID(uuid)); assertTrue(removed.isEmpty()); } + + @AfterEach + void tearDown() { + databaseManager.disconnect(); + } } From 4619bcc0dfe2a97ee1d8a7518de9d4499460799d Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:23:32 +0100 Subject: [PATCH 42/43] Fail-fast if table creation does not succeed --- .../parcel/repository/ParcelRepositoryOrmLite.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index cdc37744..ff47d13f 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -32,7 +32,7 @@ public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler schedu TableUtils.createTableIfNotExists(databaseManager.connectionSource(), ParcelWrapper.class); } catch (SQLException ex) { Sentry.captureException(ex); - ex.printStackTrace(); + throw new RuntimeException("Failed to initialize parcel table", ex); } } From 7e978f04ac8441723312bdb7a83190f8285d1d4e Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:32:04 +0100 Subject: [PATCH 43/43] [ci skip] Assign databaseManager field --- src/main/java/com/eternalcode/parcellockers/ParcelLockers.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index e7a7ed70..47bc9dae 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -113,6 +113,7 @@ public void onEnable() { LoggerFactory.setLogBackendFactory(new NullLogBackend.NullLogBackendFactory()); DatabaseManager databaseManager = new DatabaseManager(config, this.getLogger(), this.getDataFolder()); + this.databaseManager = databaseManager; try { databaseManager.connect();