-
-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GH-78 Rewrite database to ORMLite JDBC #116
Conversation
…y database classes
# Conflicts: # build.gradle.kts
Warning Rate limit exceeded@Jakubk15 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 13 minutes and 42 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThe pull request introduces a comprehensive refactoring of the database layer in the ParcelLockers plugin, transitioning from a custom database implementation to an ORM Lite (Object-Relational Mapping Lite) approach. This change involves replacing existing repository implementations with ORM Lite versions, introducing new wrapper classes for database entities, and updating the database management strategy. The modifications support multiple database types, including H2, PostgreSQL, and MySQL, with improved configuration and connection handling. Assessment against linked issues
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🔭 Outside diff range comments (1)
src/main/java/com/eternalcode/parcellockers/user/UserManager.java (1)
Line range hint
51-63
: Potential Concurrency Issues increate(UUID uuid, String name)
While the
create
method works for a single-threaded approach, concurrent calls can pose these risks:
- Race Conditions: Two threads creating the same user simultaneously might slip past the
containsKey
checks.- Repository Consistency: A user might fail to be saved if an exception occurs in the repository, potentially leaving the in-memory map out of sync.
To address these concerns, consider atomic checks or synchronization around map updates, or rely on your repository if it can guarantee uniqueness at the database level.
🧹 Nitpick comments (33)
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java (1)
22-22
: Document the return value meaning
Changing the return type fromCompletableFuture<Void>
toCompletableFuture<Integer>
is beneficial, as it allows for tracking how many records were removed. However, please add or update documentation to clarify what the returned integer represents (e.g., the count of removed rows or an indicator of success/failure).src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java (4)
9-10
: Consider class visibility for broader usage.
By default, this class is package-private. If future features or modules outside this package will need direct access toUserWrapper
, consider using thepublic
modifier.
15-16
: Specify additional column constraints for robustness.
If there is a maximum length or uniqueness requirement forusername
, consider leveraging ORMLite’s@DatabaseField
attributes (e.g.,width
,unique
) to ensure better data consistency and constraints.
26-28
: Validate non-null argument to avoid potentialNullPointerException
.
Ifuser
is ever null,user.uuid()
anduser.name()
would raise an exception. Consider adding a null check or clarifying in the method contract thatuser
must not be null.
30-32
: Check consistency of exposure vs. encapsulation.
setUsername(...)
is declared public while the class itself is package-private. If external consumers need to updateusername
, ensure that the class is likewise accessible; otherwise, consider limiting the visibility of this setter.src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java (2)
22-28
: Consider avoiding double-logging exceptions.Here, the code captures exceptions with Sentry and also prints the stack trace. This can lead to duplicate logs. Typically, either logging to Sentry with supplemental log statements or printing stack traces individually should suffice.
try { TableUtils.createTableIfNotExists(databaseManager.connectionSource(), UserWrapper.class); } catch (SQLException exception) { Sentry.captureException(exception); - exception.printStackTrace(); }
58-74
: Revisit the pagination logic when checkinghasNext
.Currently, the query limits results to
page.getLimit()
, so you do not fetch an extra record to determine if more data exists. If you'd like to confirm there is more data, you might need to query forlimit + 1
rows and then remove the last row if it exists.List<User> users = dao.queryBuilder() - .offset((long) page.getOffset()) - .limit((long) page.getLimit()) + .offset((long) page.getOffset()) + .limit((long) (page.getLimit() + 1)) .query() .stream() .map(UserWrapper::toUser) .collect(Collectors.toList()); boolean hasNext = users.size() > page.getLimit(); if (hasNext) { users.remove(users.size() - 1); }src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java (3)
17-19
: Use more descriptive parameter names for clarity
In methods likesave(Class<T> type, T warp)
, the parameter namewarp
can be confusing. Consider renaming this parameter to something more descriptive, such asentity
.
53-55
: Provide a custom Executor or clarify concurrency requirements
CompletableFuture.runAsync(...)
uses the common ForkJoinPool by default, which may be undesirable in some scenarios (e.g., heavy I/O operations or concurrency constraints). Consider providing a custom Executor if you need stricter control over threading or concurrency.
62-66
: Avoid printing stack traces after sending them to Sentry
You are already capturing exceptions with Sentry. Printing stack traces manually might create redundant logs. Instead, consider using a logger at a suitable log level if needed for local debugging.src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java (2)
30-36
: Consider removing raw exception printing
You capture exceptions with Sentry but also callex.printStackTrace()
. You may want to switch to a standard logger to ensure consistent logging across the application.
38-42
: Check for cache and database consistency
Whensave(Parcel parcel)
completes asynchronously, the parcel is added to the cache immediately but the database operation is still pending. In highly concurrent scenarios, this might momentarily create inconsistencies. Consider documenting or synchronizing the cache update if consistency is critical.src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java (1)
118-124
: Handle potential concurrency race conditions in updateCaches()
The method clears and repopulates caches asynchronously. If other threads are reading or writing at the same time, keys may vanish or reappear in unexpected ways. Add explicit synchronization or use thread-safe structures to ensure data consistency.src/main/java/com/eternalcode/parcellockers/ParcelLockers.java (5)
112-113
: ORMLite log set to NullLogBackend.
Double-check if you want all logs suppressed. Debugging database operations may be harder without logs.
114-123
: Instantiation and connection ofDatabaseManager
.
While this works, consider instantiating directly into the field and connecting within the try block to avoid potential scoping confusion. Also consider adding more descriptive error handling or fallback logic in case of failures.
134-135
:ItemStorageRepositoryOrmLite
creation.
Implementation looks straightforward. The blank line may be removed for cleanliness.
186-189
: Gracefully disconnecting from the database.
Consider wrappingdisconnect()
in a try-catch block to handle potential close errors or log them.
208-208
: MC version support warning updated.
You might want to mention your newly supported range in documentation for clarity.src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageWrapper.java (1)
29-35
: Enforce immutability of domain objects if permissible.
Currently,List<ItemStack> items
is mutable and returned directly viatoItemStorage()
. If the data should be immutable after loading from DB, consider returning an unmodifiable list.src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java (3)
12-13
: Check table naming consistency.
Ensure that"parcel_content"
aligns with naming conventions used across the project. In some teams, table names are all plural or all singular. This keeps your schema consistent if you have multiple domain objects.
15-19
: Consider data growth strategy.
Similar toItemStorageWrapper
, this class stores a list ofItemStack
objects in a single column. Evaluate your expected row sizes—if you need advanced queries on these items, normalizing or splitting them across multiple records may be more scalable.
29-35
: Avoid passing mutable data.
When converting toParcelContent
, consider returning an unmodifiable or defensive copy of the items list to prevent in-place modifications that might drift from the state saved in the database.src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java (1)
11-12
: Use consistent naming for table columns.
@DatabaseTable(tableName = "lockers")
is clear, but verify that other similar domain objects use either “plural” or “singular” naming for table names.src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java (1)
19-25
: Improve exception logging.
In addition to capturing the exception in Sentry, consider using a logger instead ofex.printStackTrace()
for consistent log formatting and better integration with logging tools.} catch (SQLException ex) { Sentry.captureException(ex); - ex.printStackTrace(); + Logger logger = LoggerFactory.getLogger(ItemStorageRepositoryOrmLite.class); + logger.error("Failed to create table", ex); }src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java (1)
28-31
: Clarify asynchronous return value
When returning aCompletableFuture<Void>
, it might be useful to capture and handle possible exceptions. Consider chaining a.exceptionally(...)
to log or manage failures, particularly for critical database write operations.src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java (2)
56-58
: Validate null arguments in static factory method
When mapping fromParcel
toParcelWrapper
, consider whether any fields can benull
and handle them gracefully to prevent potentialNullPointerException
.
60-62
: Review single-element Set usage
ThetoParcel()
method creates aSet
with only the sender. If multi-sender support is planned, consider adjusting or adding an appropriate collection. Otherwise, document this design choice for clarity.src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java (3)
17-17
: Importing File for local data storage
Usingjava.io.File
is standard, but ensure the hard-coded paths in this test file do not conflict with other test environments or CI servers.
20-20
: Java Logger usage
Utilizingjava.util.logging.Logger
is acceptable. However, if your project uses SLF4J or another logging framework in production, consider aligning the test with the same logger approach for consistency.
33-33
: Hard-coded data folder path
Storing data under"run/plugins/ParcelLockers"
works locally but could be less flexible in CI or other environments. Consider using a parameterized or temporary folder for improved test portability.- File dataFolder = new File("run/plugins/ParcelLockers"); + File dataFolder = Files.createTempDirectory("ParcelLockersTest").toFile();src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java (3)
47-49
: Expose pool size and timeouts to config
Hardcoding HikariCP parameters can limit flexibility. Consider making these properties configurable inPluginConfiguration
.this.dataSource.setMaximumPoolSize(5); this.dataSource.setConnectionTimeout(5000); this.dataSource.setLeakDetectionThreshold(5000); + // e.g., this.dataSource.setMaximumPoolSize(config.settings.poolSize); + // this.dataSource.setConnectionTimeout(config.settings.connectionTimeout); + // this.dataSource.setLeakDetectionThreshold(config.settings.leakDetectionThreshold);
65-68
: Potential cross-platform path issue
For H2,jdbc:h2:./
plusFile
might cause path separators issues on some systems. Consider usingdataFolder.getAbsolutePath()
or a platform-agnostic approach.
99-114
: Concurrent access to cached DAO
Using aConcurrentHashMap
is good, but creating a DAO in a race could produce redundant entries. Prevent this withcomputeIfAbsent
or similar.Dao<?, ?> dao = this.cachedDao.computeIfAbsent(type, key -> { try { return DaoManager.createDao(this.connectionSource, key); } catch (SQLException exception) { throw new RuntimeException(exception); } });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (41)
TODO.md
(1 hunks)build.gradle.kts
(3 hunks)src/main/java/com/eternalcode/parcellockers/ParcelLockers.java
(7 hunks)src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryImpl.java
(0 hunks)src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java
(0 hunks)src/main/java/com/eternalcode/parcellockers/database/DataSourceFactory.java
(0 hunks)src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/database/DatabaseType.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/LockerMainGUI.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelItemStorageGUI.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelSendingGUI.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ReceiverSelectionGui.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepository.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryImpl.java
(0 hunks)src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageWrapper.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java
(0 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java
(0 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/shared/Position.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/user/UserManager.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/user/UserPageResult.java
(0 hunks)src/main/java/com/eternalcode/parcellockers/user/UserRepositoryImpl.java
(0 hunks)src/main/java/com/eternalcode/parcellockers/user/repository/UserPageResult.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/user/repository/UserRepository.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java
(1 hunks)src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java
(2 hunks)src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java
(2 hunks)src/test/java/com/eternalcode/parcellockers/database/ParcelLockerIntegrationSpec.java
(0 hunks)
💤 Files with no reviewable changes (9)
- src/main/java/com/eternalcode/parcellockers/user/UserPageResult.java
- src/test/java/com/eternalcode/parcellockers/database/ParcelLockerIntegrationSpec.java
- src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryImpl.java
- src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryImpl.java
- src/main/java/com/eternalcode/parcellockers/database/AbstractDatabaseService.java
- src/main/java/com/eternalcode/parcellockers/database/DataSourceFactory.java
- src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryImpl.java
- src/main/java/com/eternalcode/parcellockers/user/UserRepositoryImpl.java
- src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryImpl.java
✅ Files skipped from review due to trivial changes (7)
- TODO.md
- src/main/java/com/eternalcode/parcellockers/user/repository/UserPageResult.java
- src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ReceiverSelectionGui.java
- src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/LockerMainGUI.java
- src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelItemStorageGUI.java
- src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/ParcelSendingGUI.java
- src/main/java/com/eternalcode/parcellockers/user/repository/UserRepository.java
🔇 Additional comments (50)
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java (1)
24-24
: Consistent handling of remove by UUID
Likewise, returning an integer here adds consistency. Verify that any consumer code handling partial or missing records is updated to interpret the integer's value correctly.
src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java (1)
12-13
: Verify database column type compatibility.
Storing a Java UUID
in the database typically requires either a VARCHAR(36)
or similar column type. Confirm that ORMLite is configured to handle the UUID
field correctly.
src/main/java/com/eternalcode/parcellockers/user/UserManager.java (3)
3-4
: Importing UserRepository
Looks Good
Bringing in the UserRepository
from com.eternalcode.parcellockers.user.repository
fits well with the new ORMLite-based design. This import is necessary for integrating the database interactions within the UserManager
.
Line range hint 16-26
: Asynchronous getUser(UUID uuid)
Implementation
Returning a CompletableFuture<Optional<User>>
is a solid choice for non-blocking I/O. This allows calls to the repository to be processed asynchronously, which can yield better performance. However, please verify:
- Thread-safety: Ensure that the
usersByUUID
map is only modified by safe operations or from a single thread, otherwise consider using concurrent structures or external synchronization. - Consistent Cache Usage: Confirm whether the cache (i.e.,
usersByUUID
) remains up-to-date whenever remote changes (e.g., name updates) occur in the repository.
Line range hint 28-38
: Asynchronous getUser(String name)
Method
Following a similar pattern to getUser(UUID)
, this asynchronous retrieval from the repository is clear. Keep an eye out for:
- Case Sensitivity: If user names ever vary in casing, consider normalizing or clarifying that names are case-sensitive.
- Performance: Double-check whether name-to-user lookups are frequent. If so, ensure that the
usersByName
map remains current to avoid stale or missing entries.
src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java (2)
38-40
: Gracefully handle null inputs
Returning null
from javaToSqlArg()
is correct, but be mindful of any further processing in the call chain where a null might cause NullPointerException
. Verify that all callers handle null
results properly.
72-77
: Consistent exception handling
Capturing exceptions with Sentry and throwing ParcelLockersException
is a good approach. Ensure that any upstream callers handle or log the exception in a user-friendly manner.
src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java (1)
36-39
: Confirm test container initialization and resource cleanup
The new approach loads configuration from disk and connects to the MySQL test container. Ensure that resource cleanup is properly handled and that leftover files in run/plugins/ParcelLockers
do not interfere with subsequent tests.
src/main/java/com/eternalcode/parcellockers/ParcelLockers.java (17)
5-6
: Imports for scheduler functionality look good.
The newly introduced scheduler imports should help streamline asynchronous tasks. Ensure you properly handle concurrency and shutdown worker threads when the plugin is disabled.
12-12
: Import for ParcelContentRepositoryOrmLite
.
This aligns with the migration to the new ORMLite-based repository. Looks consistent with the PR objectives.
13-13
: Import for DatabaseManager
.
Matches the new refactored approach for database handling. No issues here.
18-18
: Import for ItemStorageRepositoryOrmLite
.
Consistent with the switch to ORMLite. Good to have a unified repository approach.
23-23
: Import for LockerRepositoryOrmLite
.
Migrating to ORM-based repository helps with cleaner database interactions.
31-31
: Import for ParcelRepositoryOrmLite
.
Complements the other repository migrations. No concerns here.
36-37
: Imports for UserRepository
and UserRepositoryOrmLite
.
Indicates a shift to an ORM-based user repository. Looks good.
39-40
: Imports for ORMLite logger classes.
Setting a null log backend might suppress important ORMLite logs. Consider using a minimal logger instead, unless silence is your intent.
60-60
: Import for SQLException
.
Necessary for robust error handling with the new database logic.
78-79
: Field databaseManager
introduced.
The field name clearly expresses its role. This refactor centralizes DB management.
96-96
: Initializing the Scheduler
implementation.
Please confirm that this scheduler
instance is utilized later in the code. If unused, consider removing or storing it for task scheduling.
107-107
: Disabling Sentry (options.setEnabled(false)
).
Revisit whether disabling Sentry here conflicts with config.settings.enableSentry
. This might override user configuration.
131-131
: LockerRepositoryOrmLite
usage.
Immediately updating caches is good for performance, but verify that it does not introduce heavy load on large datasets. Lazy-loading strategies or partial caching might be beneficial if the dataset grows large.
136-136
: ParcelRepositoryOrmLite
creation.
Consistent with the ORMLite approach. No issues.
140-140
: UserRepositoryOrmLite
assignment.
Smooth integration with UserManager
. Looks well-structured.
143-143
: ParcelContentRepositoryOrmLite
usage.
Good alignment with the new ORM architecture.
212-212
: Conditional check for version 17 or 21.
The OR condition might exclude versions between 18–20. If you intend multi-version support, verify that your condition is correct.
src/main/java/com/eternalcode/parcellockers/database/DatabaseType.java (1)
5-8
: Newly added database types.
Supporting H2
, POSTGRESQL
, and MARIADB
expands compatibility. Note that MariaDB can often be treated similarly to MySQL, so ensure your code handles their small differences if any.
src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepository.java (1)
15-15
: Changed remove
method return type to CompletableFuture<Integer>
.
Returning the number of removed items (instead of void) makes the API more expressive. Great improvement.
src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java (1)
13-13
: Updated remove
to return an integer.
This adds clarity about how many records were removed, aligning with other repositories.
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java (3)
23-23
: remove(UUID)
now returns CompletableFuture<Integer>
.
Returning the count is good for validation or logging.
25-25
: remove(Locker)
similarly updated.
Consistent approach for remove
. This helps unify repository expectations.
29-29
: Renamed findLocker(uuid)
to getFromCache(uuid)
.
The name emphasizes cache usage, which is more descriptive. Ensure there's a fallback if the cache is stale or empty.
src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageWrapper.java (2)
18-19
: Verify the persister for a list of ItemStacks.
Storing a collection of complex objects such as ItemStack
in a single table column can be fragile—especially when item data can be large or frequently updated. Ensure that ItemStackPersister
thoroughly handles edge cases (e.g., corrupted data, partial updates).
12-13
: Consider explicit access modifier.
Currently, the class is package-private. If other packages need to utilize ItemStorageWrapper
, consider marking the class public
, or providing factory methods/services within the same package to manage visibility.
Would you like me to search for references to ItemStorageWrapper
outside this package to confirm whether it should be public
?
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java (2)
14-21
: Check data constraints for fields.
The description
field currently has no length or nullability constraints. If it can be very large or null, ensure the schema and code handle that properly.
32-38
: Ensure domain-object integrity.
Locker
is reconstructed directly from LockerWrapper
. Confirm that no additional data validations are needed (e.g., checking for null uuid
or invalid position
).
[approve]
src/main/java/com/eternalcode/parcellockers/itemstorage/repository/ItemStorageRepositoryOrmLite.java (2)
28-30
: Clarify the handling of DAO in save
method.
The completion stage discards the DAO reference (thenApply(dao -> null)
). Confirm that ignoring the DAO is intended, or if an additional operation should be performed with the DAO result.
38-39
: Confirm correct row count for remove operation.
Returning an Integer
row count is valuable, but ensure in tests or at call sites that removing a nonexistent entry returning 0 does not cause confusion.
src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java (2)
19-25
: Consider handling table creation exceptions more gracefully
Catching and printing stack traces is helpful for debugging, but for production systems, consider more robust exception handling (e.g., re-throwing a custom runtime exception, or ensuring logs are stored with proper context).
44-45
: Check for potential null in parcelContentWrapper
When mapping via Optional.ofNullable(...)
, ensure parcelContentWrapper
itself is not null. Though the code is currently safe, consider a null check or a default value to avoid subtle runtime errors if select(...)
returns null
unexpectedly.
src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java (1)
59-67
: Validate format when splitting the deserialized string
Splitting on '/'
without robust validation can lead to ArrayIndexOutOfBoundsException
if the stored string is malformed. Consider verifying that params.length == 4
before parsing.
src/main/java/com/eternalcode/parcellockers/shared/Position.java (1)
58-58
: Ensure world is not null before checking
The updated logic checks if this.world
is empty, but does not handle null
. If world
might be null, consider a null-safe check or fallback to an empty string before comparison.
src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java (5)
3-4
: New imports for Configuration Manager and Plugin Configuration
These imports appear correct and are used consistently below. Good job ensuring the configuration and manager are introduced properly in this test.
8-8
: Switching to ORM Lite repository
Importing the LockerRepositoryOrmLite
is in line with the PR’s migration to ORM Lite. This is well-aligned with the new database approach.
34-34
: Configuration loading
It’s good that the configuration is loaded in a straightforward manner. Ensure that you have test coverage to validate behavior when the config file is missing or malformed.
35-35
: DatabaseManager instantiation
This follows the new design nicely. Make sure to verify the database manager is properly closed or disconnected at the end of the test to avoid resource leaks.
37-37
: Repository assignment
Assigning the repository to the new ORM Lite class is consistent with the PR’s objectives. The usage in subsequent lines appears cohesive with the new database logic.
build.gradle.kts (4)
30-30
: Updated API version
Switching to 1.21.4-R0.1-SNAPSHOT
aligns with the new Minecraft version target. Ensure you’ve tested compatibility thoroughly.
60-62
: Adding ORM Lite, H2, and PostgreSQL dependencies
Great job adding essential dependencies for the new database architecture. Verify that the correct versions are shaded or included in the plugin jar if your production environment needs them packaged.
133-133
: Bumping the run server version
Ensure the updated test environment (1.21.4
) is stable in your CI or local environment.
141-141
: New jar naming convention
Renaming your output for broader version compatibility is clear and helpful for end users.
src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/user/repository/UserRepositoryOrmLite.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/database/DatabaseManager.java
Outdated
Show resolved
Hide resolved
This *partially* reverts commit 953942a
...in/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java
(1 hunks)src/test/java/com/eternalcode/parcellockers/TestScheduler.java
(1 hunks)
🔇 Additional comments (7)
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java (3)
11-12
: Nice work on the class design!The package-private visibility and table naming are well thought out.
20-21
: Check the unique position constraint.The unique position makes sense, but please verify:
- What happens when a locker is deleted and a new one is created at the same spot?
- Is there any cleanup needed?
23-30
: Good job with the constructors!Both the default constructor (needed for ORMLite) and the full constructor are properly implemented.
src/test/java/com/eternalcode/parcellockers/TestScheduler.java (4)
18-22
: Implementation looks good!The synchronous task execution is implemented correctly.
24-28
: Implementation looks good!The asynchronous execution using CompletableFuture is well implemented.
54-62
: Review identical implementationsThe
complete
andcompleteAsync
methods have the same implementation. Consider if they should behave differently.
64-85
: Implementation looks good!The Task implementation has been improved to correctly handle both CompletableFuture and ScheduledFuture.
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/database/wrapper/AbstractRepositoryOrmLite.java
Show resolved
Hide resolved
...in/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java
Outdated
Show resolved
Hide resolved
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 17
♻️ Duplicate comments (4)
src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java (1)
24-33
: 🛠️ Refactor suggestionConsider using JSON for robust serialization.
The current string concatenation approach might have issues with special characters in world names.
Note: This is a duplicate of a previous comment where JSON serialization was suggested as a more robust solution.
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java (1)
35-39
: 🧹 Nitpick (assertive)Consider adding indexes for locker fields
Since
entryLocker
anddestinationLocker
are likely to be frequently queried, adding indexes could improve performance.- @DatabaseField(columnName = "entryLocker") + @DatabaseField(columnName = "entryLocker", index = true) private UUID entryLocker; - @DatabaseField(columnName = "destinationLocker") + @DatabaseField(columnName = "destinationLocker", index = true) private UUID destinationLocker;src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java (1)
33-35
: 🧹 Nitpick (assertive)Consider removing redundant error logging
The
ex.printStackTrace();
line might be unnecessary since the exception is already captured by Sentry and rethrown. Removing it can clean up the console output.Apply this change:
} catch (SQLException ex) { Sentry.captureException(ex); - ex.printStackTrace(); throw new RuntimeException("Failed to initialize locker table", ex); }
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java (1)
32-34
: 🧹 Nitpick (assertive)Add null check for safety
Adding a null check for the
locker
parameter can prevent potential issues if a null value is passed.Consider updating the method:
static LockerWrapper from(Locker locker) { + if (locker == null) { + throw new IllegalArgumentException("Locker cannot be null"); + } return new LockerWrapper(locker.uuid(), locker.description(), locker.position()); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (13)
build.gradle.kts
(3 hunks)src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/database/persister/ItemStackPersister.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerWrapper.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java
(1 hunks)src/test/java/com/eternalcode/parcellockers/TestScheduler.java
(1 hunks)
🔇 Additional comments (14)
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java (2)
22-22
: Changes look goodThe updates to the
remove
methods' return types make sense.Also applies to: 24-24
30-30
: The method rename is clearRenaming to
findParcelFromCache
accurately reflects its purpose.src/test/java/com/eternalcode/parcellockers/TestScheduler.java (3)
18-20
: Great job adding the shutdown method!
35-38
: Please handle negative durationsIt's a good idea to check if the duration is negative to prevent unexpected behavior.
47-50
: Please handle negative durationsMake sure to validate that
initialDelay
andperiod
are not negative.src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java (2)
1-12
: Nice work on the class setup!The class is well-organized with appropriate visibility and annotations.
41-54
: Well-structured constructors!Both the default constructor (required by ORMLite) and the all-args constructor are properly implemented.
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java (3)
40-45
: Cache update after successful save looks goodUpdating the cache after the locker is saved ensures consistency between the database and the cache. Nice work!
24-25
: Great choice using ConcurrentHashMapUsing
ConcurrentHashMap
forcache
andpositionCache
helps handle concurrent access safely. Good job!
62-64
:⚠️ Potential issueFix method usage when accessing list elements
Instead of
lockers.getFirst()
, which isn't a standard method forList
, uselockers.get(0)
to get the first element.Here's the fix:
return lockers.isEmpty() ? Optional.empty() : Optional.of(lockers.getFirst().toLocker()); + return lockers.isEmpty() ? Optional.empty() : Optional.of(lockers.get(0).toLocker());
Likely invalid or redundant comment.
src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepository.java (1)
13-13
: Ensure that the return type change forremove
method is handled properlyJust wanted to mention that changing the return type from
CompletableFuture<Void>
toCompletableFuture<Integer>
might affect existing code that uses this method. Please make sure to update any implementations or calls to handle the new return type.You can run the following script to find all usages of the
remove
method and ensure they are updated accordingly:✅ Verification successful
Return type change is safe to proceed
The code currently ignores the return value in all places where
remove()
is called, so changing fromVoid
toInteger
won't cause any issues.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Find all usages of 'remove' method in 'ParcelContentRepository' and check for handling of the return value. rg 'ParcelContentRepository.*\.remove\(' -g '*.java' -t javaLength of output: 62
Script:
#!/bin/bash # Find implementations and usages with broader patterns echo "=== Finding interface implementations ===" ast-grep --pattern 'class $_ implements $$$ParcelContentRepository$$$' echo -e "\n=== Finding all remove method calls with UUID parameter ===" rg '\.remove\(\s*[a-zA-Z0-9_]+\.getUniqueId\(\)\s*\)' -t java echo -e "\n=== Finding imports of ParcelContentRepository ===" rg "import.*ParcelContentRepository" -t javaLength of output: 1876
src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java (1)
29-31
: Consider returning the saved entityThe save operation could return the saved entity for further use, as suggested in previous reviews.
-public CompletableFuture<Void> save(ParcelContent parcelContent) { - return this.saveIfNotExist(ParcelContentWrapper.class, ParcelContentWrapper.from(parcelContent)).thenApply(dao -> null); +public CompletableFuture<ParcelContent> save(ParcelContent parcelContent) { + return this.saveIfNotExist(ParcelContentWrapper.class, ParcelContentWrapper.from(parcelContent)) + .thenApply(wrapper -> wrapper.toParcelContent());build.gradle.kts (2)
141-141
: Verify version compatibilityThe version range has been narrowed from 1.8.8-1.21.x to 1.21.3-1.21.4. Make sure this change is intentional and all features are compatible with this range.
128-128
: Document Java 21 requirementThe upgrade to Java 21 is significant. Consider adding a note in the README about this requirement.
src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentWrapper.java
Show resolved
Hide resolved
...in/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java
Outdated
Show resolved
Hide resolved
...in/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
🔭 Outside diff range comments (2)
src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java (2)
Line range hint
56-76
: Simplify the break operationSince we already have the locker in cache, we can simplify this:
- this.lockerRepository.findByPosition(position).thenAccept((locker) -> { - if (locker.isEmpty()) { - return; - } - - UUID toRemove = this.cache.get(position).get().uuid(); + this.cache.get(position).ifPresent(locker -> { + UUID toRemove = locker.uuid(); this.lockerRepository.remove(toRemove); this.announcer.sendMessage(player, this.messages.parcelLockerSuccessfullyDeleted); Formatter formatter = new Formatter() .register("{X}", position.x()) .register("{Y}", position.y()) .register("{Z}", position.z()) .register("{WORLD}", position.world()) .register("{PLAYER}", player.getName()); this.announcer.broadcast(formatter.format(this.messages.broadcastParcelLockerRemoved)); - }); + });
Line range hint
82-127
: Reduce repeated codeAll these event handlers do the same check. Let's create a helper method:
+ private boolean isLockerPosition(Position position) { + return this.cache.get(position).isPresent(); + } @EventHandler public void onBlockBurn(BlockBurnEvent event) { Position position = PositionAdapter.convert(event.getBlock().getLocation()); - if (this.cache.get(position).isPresent()) { + if (isLockerPosition(position)) { event.setCancelled(true); } }
♻️ Duplicate comments (2)
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java (1)
104-108
: 🛠️ Refactor suggestionUpdate cache atomically in
updateCaches()
Clearing and repopulating the cache asynchronously can lead to inconsistent reads. Consider updating the cache atomically.
src/main/java/com/eternalcode/parcellockers/ParcelLockers.java (1)
121-123
: 🧹 Nitpick (assertive)Handle database connection failures without stopping the plugin
Throwing a
RuntimeException
stops the plugin if the database connection fails. Maybe catch the exception and allow the plugin to keep running, even if some features won't work.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (11)
src/main/java/com/eternalcode/parcellockers/ParcelLockers.java
(8 hunks)src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java
(2 hunks)src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java
(8 hunks)src/main/java/com/eternalcode/parcellockers/locker/controller/LockerInteractionController.java
(3 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerCache.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java
(2 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelCache.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java
(1 hunks)
🔇 Additional comments (15)
src/main/java/com/eternalcode/parcellockers/locker/controller/LockerInteractionController.java (4)
4-4
: Import updated to LockerCache
18-18
: Nice switch to use LockerCache
21-22
: Constructor adjusted appropriately
39-39
: Cache check updated nicelysrc/main/java/com/eternalcode/parcellockers/locker/repository/LockerCache.java (1)
14-15
: Good choice using ConcurrentHashMap!Using thread-safe maps is perfect for handling multiple requests at once.
src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java (3)
13-15
: Looking good!The switch to LockerCache makes sense and follows the PR's goal of improving data access.
17-19
: Nice and clean!The constructor is simple and does its job well.
Line range hint
1-12
: Check for consistent cache usage across the projectLet's make sure other classes are also using LockerCache consistently.
✅ Verification successful
All good! The cache and repository are working together as intended
The code shows a proper setup where LockerCache complements LockerRepository instead of replacing it. This is exactly how it should work! 🎯
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for any remaining LockerRepository usage rg "LockerRepository" -l # Search for LockerCache usage rg "LockerCache" -lLength of output: 1863
Script:
#!/bin/bash # Check content of files containing both echo "=== ParcelLockers.java ===" rg "LockerRepository|LockerCache" src/main/java/com/eternalcode/parcellockers/ParcelLockers.java -B 1 -A 1 echo -e "\n=== LockerBreakController.java ===" rg "LockerRepository|LockerCache" src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java -B 1 -A 1 echo -e "\n=== LockerRepositoryOrmLite.java ===" rg "LockerRepository|LockerCache" src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepositoryOrmLite.java -B 1 -A 1Length of output: 2144
src/main/java/com/eternalcode/parcellockers/ParcelLockers.java (1)
213-213
: Check the version support logicYou're warning about supported versions from 1.17.x to 1.21.x, but the code only checks for version 17. Consider updating the check to cover the entire range.
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java (2)
15-15
: The addition offindAll()
looks good!Adding
findAll()
enhances parcel retrieval options.
23-25
: Changing return types ofremove
methods seems appropriate.Switching to return
CompletableFuture<Integer>
allows for tracking the number of parcels removed.src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java (1)
34-35
: Consider replacingex.printStackTrace()
with proper logging.Using
ex.printStackTrace()
may clutter the console.src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelCache.java (1)
1-38
: TheParcelCache
implementation looks good!This class provides efficient caching of parcels.
src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java (2)
4-4
: LGTM! Clean import additions.The new imports support the cache-based implementation nicely.
Also applies to: 14-14
19-22
: Nice and clean dependency injection!The switch to ParcelCache is implemented well with proper constructor injection.
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerCache.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerCache.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/locker/repository/LockerRepository.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java
Outdated
Show resolved
Hide resolved
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java
Outdated
Show resolved
Hide resolved
…ParcelWrapper.java Co-authored-by: DMK <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java (1)
60-62
:⚠️ Potential issueFix data loss in toParcel() method.
The
toParcel()
method is losing data by only using the sender as the allowed sender. We need to store and restore all allowed senders.Add a field to store all allowed senders:
+ @DatabaseField(columnName = "allowed_senders") + private String allowedSenders; // Store as comma-separated UUIDs 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); + Set<UUID> allowedSenderSet = Arrays.stream(this.allowedSenders.split(",")) + .map(UUID::fromString) + .collect(Collectors.toSet()); + return new Parcel(this.uuid, this.sender, this.name, this.description, this.priority, allowedSenderSet, this.receiver, this.size, this.entryLocker, this.destinationLocker); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java
(1 hunks)
🔇 Additional comments (2)
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java (2)
1-12
: Looking good! Clean class setup.The class structure and annotations are well-organized.
41-54
: Perfect constructor setup!Both the no-args constructor (required by ORMLite) and the full constructor are properly implemented.
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java
Outdated
Show resolved
Hide resolved
…ParcelWrapper.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: DMK <[email protected]>
…/PositionPersister.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…/PositionPersister.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…/ParcelContentRepositoryOrmLite.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
♻️ Duplicate comments (3)
src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java (1)
32-37
: 🧹 Nitpick (assertive)Consider caching the suggestions for better performance.
Since locker descriptions don't change often, we could avoid creating new streams each time.
src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java (2)
29-31
: 🧹 Nitpick (assertive)Consider returning the saved ParcelContent
Returning the saved
ParcelContent
might be useful for future operations.
39-41
:⚠️ Potential issueWatch out for a null pointer exception
If
parcelContentWrapper
is null, callingtoParcelContent()
could cause an exception. Let's handle this safely.Here's a suggestion to fix it:
return this.select(ParcelContentWrapper.class, uniqueId) - .thenApply(parcelContentWrapper -> Optional.ofNullable(parcelContentWrapper.toParcelContent())); + .thenApply(parcelContentWrapper -> { + if (parcelContentWrapper == null) { + return Optional.empty(); + } else { + return Optional.of(parcelContentWrapper.toParcelContent()); + } + });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (9)
src/main/java/com/eternalcode/parcellockers/ParcelLockers.java
(8 hunks)src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java
(2 hunks)src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java
(2 hunks)src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java
(1 hunks)src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java
(1 hunks)src/test/java/com/eternalcode/parcellockers/database/ParcelDatabaseServiceIntegrationTest.java
(2 hunks)src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java
(3 hunks)
🧰 Additional context used
📓 Learnings (1)
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java (1)
Learnt from: Jakubk15
PR: EternalCodeTeam/ParcelLockers#116
File: src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java:59-61
Timestamp: 2025-01-15T20:13:38.696Z
Learning: The ParcelWrapper class currently only stores a single sender, while the Parcel class supports multiple allowed senders. This limitation will be addressed in a future PR.
🔇 Additional comments (17)
src/main/java/com/eternalcode/parcellockers/locker/argument/ParcelLockerArgument.java (4)
Line range hint
1-11
: Nice package restructuring!The move to
locker.argument
package makes more sense with the new database design.
13-15
: Good field update!The switch to
LockerCache
aligns well with the new caching strategy.
17-19
: Clean constructor update!The constructor properly initializes the cache field.
22-28
: Great job implementing the suggested improvements!The parse method looks cleaner with the
map(ParseResult::success)
approach.src/main/java/com/eternalcode/parcellockers/user/repository/UserWrapper.java (4)
9-10
: Consider making the class public and the table name configurable.The class might need to be accessed from other packages, and the table name could be made configurable for different environments.
18-24
: Add constructor validation and documentation.The default constructor needs documentation explaining it's for ORMLite, and the parameterized constructor should validate its inputs.
26-36
: Add validation to conversion methods.The conversion methods need null checks and validation.
15-16
: 🧹 Nitpick (assertive)Add length validation for username.
Consider adding a maximum length limit to prevent overly long usernames.
- @DatabaseField(index = true, unique = true, canBeNull = false) + @DatabaseField(index = true, unique = true, canBeNull = false, width = 32) private String username;Likely invalid or redundant comment.
src/main/java/com/eternalcode/parcellockers/parcel/command/argument/ParcelArgument.java (2)
27-34
: Good job handling invalid UUID inputs.
39-41
: Consider renamingcache.cache()
to improve clarity.src/main/java/com/eternalcode/parcellockers/content/repository/ParcelContentRepositoryOrmLite.java (1)
20-25
: Nice exception handlingGood job capturing exceptions with Sentry and throwing a RuntimeException to handle critical errors.
src/main/java/com/eternalcode/parcellockers/ParcelLockers.java (1)
190-192
: EnsuredatabaseManager
is properly initialized before disconnectingSince
databaseManager
might not have been assigned to the class variable, callingthis.databaseManager.disconnect();
could lead to aNullPointerException
. After assigning it correctly in theonEnable
method, this issue will be resolved.src/main/java/com/eternalcode/parcellockers/database/persister/PositionPersister.java (2)
24-26
: Add a null check forjavaObject
injavaToSqlArg
Adding a null check here can prevent potential
NullPointerException
ifjavaObject
is null.
25-32
: Handle special characters inworldName
during serializationIf
worldName
contains'/'
, it could cause issues when deserializing. Consider escaping special characters or using a different serialization format like JSON.src/test/java/com/eternalcode/parcellockers/database/ParcelLockerDatabaseServiceIntegrationTest.java (1)
75-78
: 🧹 Nitpick (assertive)Let's check if
databaseManager
is not null before disconnecting to avoid any issues.Apply this diff:
@AfterEach void tearDown() { - databaseManager.disconnect(); + if (databaseManager != null) { + databaseManager.disconnect(); + } }Likely invalid or redundant comment.
src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelWrapper.java (2)
14-39
: Field declarations look great!Good job adding indexes on frequently queried fields. The field names and types are clear and appropriate.
59-61
: 🧹 Nitpick (assertive)Add a TODO comment about the multiple senders limitation.
Based on the retrieved learnings, this is a known limitation that will be addressed in a future PR.
+ // TODO: Support multiple senders in a future PR - currently only stores the primary sender Parcel toParcel() {
Likely invalid or redundant comment.
Resolves #78
Adds support for more database types as well as rewrites general database logic to use the j256/ormlite-jdbc library.