Repository navigation
26.3 - #22
Open
vilhu-github wants to merge 7 commits into
Open
26.3#22vilhu-github wants to merge 7 commits into
vilhu-github wants to merge 7 commits into
Conversation
- Replace TNIL's PaperMapColorComponent with a copy that disables itself when DataComponentTypes.MAP_COLOR is missing (removed in Paper 26.3), fixing NoSuchFieldError on enable. - Register the String -> Material conversion TNIL uses for decorated pot sherds, fixing DECORATED_POT round trips. Verified with tests/paper-items on Paper 26.3-200 and 1.21.11-132.
Balance changes could silently disappear: - Concurrent transactions (e.g. async Vault calls) wrote ending balances calculated from stale holdings; 16 threads x 500 deposits kept 2562/8000. Transactions now run under one lock and recalculate ending balances from current holdings before applying them. - /tne reload, /tne reloaddb and Data.Sync.Reload replaced in-memory accounts with database data without saving first. They now flush. - Saves cleared the dirty flag after writing, dropping changes made while a save ran. The flag is cleared before reading and restored on failure. - Holdings are now written in one transaction per account and a failed write is retried, instead of being logged and forgotten. - Online players are always saved when an item currency exists, since item balances change without marking the wallet dirty. - Failed YAML saves no longer leave the file locked forever. All writes now run on one TNE-Storage thread: autosaves can no longer overlap or spawn Craft Scheduler threads, and shutdown flushes queued saves. Plugin core's storage worker is stopped explicitly, removing a 10 second stall on every server stop. tests/storage/SaveProbe covers concurrency, reloaddb and restart.
- SQL receipts were reloaded without participants, so after a restart no receipt matched any account and history showed nothing. Participants, modifiers and holdings are now loaded with one query per table. - Receipt tables were keyed on the receipt id alone, so only the first participant (the payer) of each payment was stored and recipients never saw incoming payments. Keys now include the participant type; existing MySQL/MariaDB tables are widened on startup. - History pages were keyed by timestamp, and receipts are stored with second precision, so all transactions within one second collapsed into one entry. Pages are now ordered lists, newest first, of the newest 200 receipts instead of 200 arbitrary ones. Same fix for missed-transaction (away) history. - Initiator shows the source (player or plugin, e.g. Vault) when a transaction has no paying account, instead of "None". - Receipts are saved in one batched transaction instead of up to a dozen statements each; 8000 receipts went from ~60 s to ~2 s. - Receipt load errors are logged instead of silently aborting the load. SaveProbe now also checks a payment receipt survives a restart with both participants.
Author
|
Sorry, didn't mean to open this PR here (yet), let me know if there are changes needed! |
Member
No problem, just let me know when you are ready for review. Happy to take a look. |
There was a problem hiding this comment.
🟡 Changes recommended
Save failures and reload ordering still allow unsaved or newer balances to be discarded or overwritten.
6 open issues
Reload shared data before restoring stale joining-account balances · New Report flush failures and prevent cache replacement · New Coordinate balance mutations with flush and cache replacement · New Restore dirty state after runtime holdings-save failures · New Restore dirty state after metadata or holdings-save exceptions · New Restore dirty flag when holdings persistence fails · New
What changed in this PR
Prepares release 0.1.5.4 with Paper 26.3 compatibility and improvements to economy persistence and transaction history.
Changes:
- Adds Paper compatibility fixes and updates release metadata.
- Centralizes storage writes and revises balance locking, reloads, and save retries.
- Repairs receipt persistence and history ordering; adds a storage regression probe.
| File | Description |
|---|---|
| tests/storage/SaveProbe.java | Adds concurrency, reload, and restart checks. |
| tests/storage/plugin.yml | Registers the storage probe plugin. |
| tests/paper-items/run.ps1 | Updates the tested plugin version. |
| tests/paper-items/README.md | Documents Paper 26.3 Java requirements. |
| TestCore/pom.xml | Updates parent version. |
| Sponge8/resources/META-INF/sponge_plugins.json | Updates plugin version. |
| Sponge8/pom.xml | Updates parent version. |
| README.md | Updates Java requirements. |
| pom.xml | Sets release version. |
| PaperCore/src/net/tnemc/paper/PaperRegistryConversions.java | Adds material conversion for decorated pots. |
| PaperCore/src/net/tnemc/item/paper/platform/impl/modern/PaperMapColorComponent.java | Guards unavailable map-color support. |
| PaperCore/resources/plugin.yml | Updates plugin version. |
| PaperCore/pom.xml | Packages compatibility override and updates versions. |
| Folia/resources/plugin.yml | Updates plugin version. |
| Folia/pom.xml | Updates dependency and parent versions. |
| Currency Templates/pom.xml | Updates parent version. |
| Core/src/net/tnemc/core/transaction/Transaction.java | Serializes balance changes and refreshes balances. |
| Core/src/net/tnemc/core/transaction/receipt/ReceiptBox.java | Preserves away receipts sharing timestamps. |
| Core/src/net/tnemc/core/transaction/history/SortedHistory.java | Lists newest receipts without timestamp collisions. |
| Core/src/net/tnemc/core/transaction/history/AwayHistory.java | Uses list-based receipt pagination. |
| Core/src/net/tnemc/core/TNEStorageProvider.java | Migrates receipt keys and routes storage work. |
| Core/src/net/tnemc/core/TNECore.java | Integrates storage-service lifecycle. |
| Core/src/net/tnemc/core/menu/TransactionMenu.java | Adapts to list-based history. |
| Core/src/net/tnemc/core/menu/BaltopMenu.java | Adapts receipt iteration. |
| Core/src/net/tnemc/core/manager/AccountManager.java | Queues new-account saves. |
| Core/src/net/tnemc/core/io/storage/SaveService.java | Adds dedicated saving, flushing, and shutdown handling. |
| Core/src/net/tnemc/core/io/storage/dialect/impl/MySQLRevampDialect.java | Enables bulk receipt-detail loading. |
| Core/src/net/tnemc/core/io/storage/dialect/impl/MySQLDialect.java | Revises receipt queries and composite keys. |
| Core/src/net/tnemc/core/io/storage/dialect/impl/MariaOutdatedDialect.java | Updates legacy MariaDB receipt storage. |
| Core/src/net/tnemc/core/io/storage/dialect/impl/MariaDialect.java | Updates MariaDB receipt queries and keys. |
| Core/src/net/tnemc/core/io/storage/datables/yaml/YAMLReceipt.java | Releases file tracking after failed saves. |
| Core/src/net/tnemc/core/io/storage/datables/yaml/YAMLHoldings.java | Releases holdings files on save exits. |
| Core/src/net/tnemc/core/io/storage/datables/yaml/YAMLAccount.java | Revises dirty flags and file cleanup. |
| Core/src/net/tnemc/core/io/storage/datables/sql/standard/SQLReceipt.java | Batches writes and reconstructs receipt participants. |
| Core/src/net/tnemc/core/io/storage/datables/sql/standard/SQLHoldings.java | Saves holdings in database transactions. |
| Core/src/net/tnemc/core/io/storage/datables/sql/standard/SQLAccount.java | Revises account-save retry handling. |
| Core/src/net/tnemc/core/handlers/player/PlayerLeaveHandler.java | Routes logout saves through the storage service. |
| Core/src/net/tnemc/core/handlers/player/PlayerJoinHandler.java | Flushes before shared-data reload. |
| Core/src/net/tnemc/core/command/TransactionCommand.java | Updates history iteration and initiator display. |
| Core/src/net/tnemc/core/command/AdminCommand.java | Integrates save and reload operations. |
| Core/pom.xml | Updates parent version. |
| BukkitEarly/resources/plugin.yml | Updates plugin version. |
| BukkitEarly/pom.xml | Updates dependency and parent versions. |
| Bukkit/resources/plugin.yml | Updates plugin version. |
| Bukkit/pom.xml | Updates parent version. |
| .changelog/0.1.5.4.md | Documents release changes and recovery limitations. |
Review effort: Balanced
| return; | ||
| } | ||
|
|
||
| TNECore.instance().saver().flush(); |
| } | ||
|
|
||
| try { | ||
| executor.submit(guard(this::saveDirty)).get(FLUSH_TIMEOUT_SECONDS, TimeUnit.SECONDS); |
| private void saveDirty() { | ||
|
|
||
| markOnlinePlayersDirty(); | ||
| datable(Account.class).ifPresent(datable->datable.storeAll(connector(), null)); |
| connection.setAutoCommit(true); | ||
| } | ||
|
|
||
| } catch(final SQLException e) { |
| account.markDirty(); | ||
| return; | ||
| } | ||
| writeAccount(yaml, account); |
Comment on lines
+160
to
173
| try { | ||
| final File accFile = new File(PluginCore.directory(), file); | ||
| if(!ensureFile(accFile, identifier)) { | ||
| return; | ||
| } | ||
| final YamlDocument yaml = loadDocument(accFile, identifier); | ||
| if(yaml == null) { | ||
| return; | ||
| } | ||
| writeHoldings(yaml, account.get()); | ||
| saveDocument(yaml, identifier); | ||
| } finally { | ||
| TNECore.yaml().remove(file); | ||
| } |
- Reloads now hold the balance lock while saving and replacing cached accounts, and are cancelled (with a message) when an account could not be saved or saving times out after 20 s, instead of wiping in-memory balances while the database is down. - Every save failure restores the dirty flag: runtime exceptions in SQL and YAML account saves, holdings reads that race a logout, and failed YAML holdings writes. - One failing account no longer aborts the rest of a save pass, and one rejected receipt no longer keeps a whole batch unsaved; receipts without a source are stored as "Unknown". - Join-time shared data reload runs before the joining account is restored, so its stale cached balance is not saved over newer data. Tested on Paper 26.3 + MariaDB 11.4: SaveProbe passes; with the database paused, /tne reloaddb is cancelled and balances stay intact, and after it returns the reload succeeds and the balance is persisted.
Two servers sharing a database still overwrite each other's balances unless they use different Core.Server.Name values or Redis sync. Also fix the javadoc link to the removed flush() method.
Balance sync sent the resulting balance, so concurrent changes on two servers overwrote each other: 400 deposits split over two servers kept 191. Servers now send the change with a unique ID; receivers drop duplicates and add it to their own balance on the server thread under the balance lock. A thread-local flag replaces plugin core's unsynced "affected accounts" list to avoid sending received changes back. TNE now runs Redis itself instead of plugin core's subscriber, which stopped for good after a Redis restart and never listened to tne:message. Messages go through one Redis stream (tne:sync): the reader resumes from its last message after reconnecting and the publisher retries in order, so nothing sent during an outage is lost. Every message carries a per-run ID next to Core.ServerID; a server copied with the same ServerID is detected and logged, and its messages are still applied. Tested with two Paper 26.3 servers, MariaDB and Redis 7: 200+200 concurrent deposits all applied on both servers; a deposit made while Redis was stopped arrived after reconnect; duplicate ServerIDs warned on both servers without losing changes. Older TNE versions cannot exchange sync messages with this one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

0.1.5.4
Major Changes
TNE-Storagethread. Autosaves no longer overlap or create newCraft Scheduler threads, and the server no longer waits 10 seconds for TNE when stopping.
Fixes
NoSuchFieldError: MAP_COLOR).No conversion registered from String to Material)./tne reload,/tne reloaddbandData.Sync.Reloaddiscarding balance changes that hadnot been saved yet.
retried.
/transactionsshowing nothing after a restart, payments missing from the recipient'shistory, and transactions made within the same second being merged into one entry. History now
shows the newest transactions first, and the initiator shows the player or plugin (e.g. Vault)
when there is no paying account.
transaction is stored.
Receipts saved before this version only kept their first participant; the missing details cannot
be recovered. Balances already lost to the bugs above need to be corrected manually.