Skip to content

Multi-server Velocity support, HikariCP connection pooling & message formatting overhaul#104

Closed
gitEpildev wants to merge 16 commits into
ez-plugins:mainfrom
gitEpildev:pr-branch
Closed

Multi-server Velocity support, HikariCP connection pooling & message formatting overhaul#104
gitEpildev wants to merge 16 commits into
ez-plugins:mainfrom
gitEpildev:pr-branch

Conversation

@gitEpildev
Copy link
Copy Markdown
Collaborator

Summary

Community contribution by @gitEpildev adding multi-server Velocity network support, replacing the single MySQL connection with HikariCP pooling, and redesigning message formatting. All original features, APIs, and plugin compatibility are preserved.

Key changes:

  • Full cross-server Velocity support — payments, real-time notifications, offline message queue, network-wide tab completion
  • HikariCP connection pooling for MySQL — replaces the single synchronized(lock) connection with a pool of 10 concurrent connections, eliminating main-thread freezes
  • Atomic MySQL transactionstransfer() uses commit/rollback for data integrity
  • 57% code reduction in MySQLStorageProvider (1,448 → 625 lines)
  • Message formatting redesign — gold for sending, green for receiving, red for errors, styled /baltop with dividers
  • Uppercase currency suffixes — K, M, B, T
  • Dedicated admin messages/eco give and /eco take have their own message keys
  • Unit tests updated to match new formatting

Note: These changes currently apply to the MySQL storage provider only. SQLite, MongoDB, and YML are unchanged.

See CHANGES.md for full details including file-by-file breakdown and setup instructions.

Files Changed

File What changed
pom.xml (parent) Added HikariCP + SLF4J dependencies, shade plugin relocation
MySQLStorageProvider.java Full rewrite: HikariCP pool, removed global lock, MySQL transactions
NumberUtil.java Uppercase K/M/B/T suffixes
BaltopCommand.java Footer divider after rank list
GiveSubcommand.java Uses eco_give message key
TakeSubcommand.java Uses eco_take message key
PaymentExecutor.java Cross-server notification support
CrossServerMessenger.java Payment notification routing, pending DB fallback
EzEconomyVelocity.java Velocity proxy plugin for message forwarding
en.yml Full message colour/formatting redesign
Unit tests Updated assertions for uppercase suffixes

Test Plan

  • Tested on live 3-server Velocity network (Lobby, US, EU)
  • Cross-server /pay works instantly with real-time notifications
  • /eco give, /eco take, /eco set all work without lag
  • /baltop displays with new styled formatting
  • Offline notification queue delivers on next login
  • No watchdog dumps or main-thread stalls
  • All existing Vault/shop/eco plugins continue working (API unchanged)

- Full cross-server payment support over Velocity networks
- Real-time payment notifications across servers
- Offline notification queue via pending_notifications DB table
- Network-wide player tab completion
- HikariCP connection pooling (replaces single synchronized connection)
- MySQL transactions for atomic transfers
- 57% code reduction in MySQLStorageProvider (1448 → 625 lines)
- Message colours: gold for sending, green for receiving, red for errors
- Redesigned /baltop with styled header and dividers
- Uppercase K/M/B/T currency suffixes
- Dedicated admin eco give/take messages
- Pre-built jars included in jars/ folder
- Unit tests updated for uppercase suffixes
Copy link
Copy Markdown
Owner

@ez-plugins ez-plugins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

I've reviewed the code. Please also add automated tests to confirm it's actually functional

Comment thread jars/ezeconomy-bukkit-2.5.1.jar Outdated
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove and add to .gitignore if it's a build file.

Comment thread jars/ezeconomy-velocity-2.5.1.jar Outdated
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove and add to .gitignore if it's a build file.

plugin.setCrossServerMessenger(messenger);
Bukkit.getPluginManager().registerEvents(this, plugin);

cleanupTaskId = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, () -> {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to me this should be optional and not started when not being used.

Comment on lines 26 to 38
// Always persist correct UUID-to-name mapping from Velocity
try {
StorageProvider storage = plugin.getStorageOrWarn();
if (storage != null) {
org.bukkit.entity.Player p = event.getPlayer();
storage.persistPlayerInfo(p.getUniqueId(), p.getName(), p.getDisplayName());
}
} catch (Exception e) {
plugin.getLogger().warning("Failed to persist player info on join: " + e.getMessage());
}

// Optionally ensure player is stored in the configured storage backend
if (!plugin.getConfig().getBoolean("store-on-join.enabled", false)) {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should only run when store-on-join is enabled, otherwise it should get it directly without the storage caching.

String senderName = in.readUTF();
String amount = in.readUTF();
String currency = in.readUTF();
plugin.getLogger().info("Received cross-server NOTIFY: recipient=" + recipientName
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make logging optional

Bukkit.getPluginManager().callEvent(payEvent);
return null;
}).get();
}).get(5, java.util.concurrent.TimeUnit.SECONDS);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace hard coded 5 seconds timeout with configurable amount or leave to default

Comment thread docs/changelog.md Outdated
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to markdown documentation updates in the docs/ folder instead

Comment thread pom.xml
Comment thread README.md
Comment thread pom.xml Outdated
@gitEpildev
Copy link
Copy Markdown
Collaborator Author

gitEpildev commented Apr 7, 2026 via email

@ez-plugins
Copy link
Copy Markdown
Owner

ez-plugins commented Apr 8, 2026

For my test/release planning, do you think it would be possible to resolve the comments before end of tomorrow?

This way I can include this in upcoming release, otherwise it would have to wait for next release since it would delay the release.

@ez-plugins
Copy link
Copy Markdown
Owner

In #105 the /pay * <amount> / /paypall <amount> option has been added. This might be of interest for this PR.

@gitEpildev
Copy link
Copy Markdown
Collaborator Author

gitEpildev commented Apr 8, 2026 via email

@ez-plugins
Copy link
Copy Markdown
Owner

That would work, thank you for your fast reply.

@gitEpildev
Copy link
Copy Markdown
Collaborator Author

gitEpildev commented Apr 8, 2026 via email

@ez-plugins
Copy link
Copy Markdown
Owner

ez-plugins commented Apr 8, 2026

Another thing I just noticed from your description, I did not check the actual code for this.

The lock is a security thing, not a performance thing.

The lock makes sure that async functionality can not be abused by spamming through packets. Making the pool 10 concurrent might create possibility to withdraw an amount 5 or 10 times while only having balance enough for 1 in the worst case when abused.

Added you on Discord.

@gitEpildev
Copy link
Copy Markdown
Collaborator Author

gitEpildev commented Apr 8, 2026 via email

@ez-plugins
Copy link
Copy Markdown
Owner

ez-plugins commented Apr 8, 2026

I have messaged you on Discord.

pterodactyl and others added 15 commits April 8, 2026 09:08
Make cross-server messaging optional with configurable verbosity, gate join-time persistence by config, harden debit paths with lock-aware withdrawal flow, and move/refresh Markdown docs for clearer navigation and release notes while aligning build metadata with upstream.
Keep cross-server pay completion, fork attribution docs, and styled pay messages while retaining upstream pay-all/config additions.
Resolve lock timing values from the active strategy config (redis.yml or bungeecord.yml), keep backward compatibility for legacy redis.* keys, and document the patch in changelog.
Normalize coverage_summary module derivation to always emit stable module names and update MySQLStorageProviderH2IntegrationTest to inject Hikari dataSource instead of legacy connection reflection.
Use strategy-agnostic lock manager protection for Vault withdraw paths, add neutral locking config keys with legacy fallback, and document the new defaults while removing duplicate GUI YAML keys.
Fix leftover lock call mismatches after cherry-pick, remove duplicate cross-server config keys, and align compact-format test expectation with uppercase suffix behavior.
Delete bundled jar binaries from git and make the unit-test coverage comment step skip fork PRs with continue-on-error so permission limits do not fail CI.
Revert the coverage summary script to the previous behavior and remove continue-on-error from the PR comment step so same-repo comment failures are visible while fork PRs still skip the step.
Delete docs/changelog.md from the repository per request.
Add eco_give, eco_take, tax_usage, baltop_footer, usage_bank_deposit,
usage_bank_withdraw to nl/es/fr/zh. Also add missing set key to fr/zh
and unknown_player to zh. Adds project .gitignore for build outputs,
IDE files, and secrets.
/pay * now includes players from all backend servers when
cross-server messaging is enabled. Each remote recipient gets
a NOTIFY forwarded through the Velocity proxy. Added Velocity
setup section, payall permissions, and proxy architecture notes
to README. Cleaned up stale assistant comment in docs/commands.md.
- BalanceCommand: add resolveOfflinePlayer helper that checks MySQL
  storage, Velocity network player list, PlayerLookup, and
  getOfflinePlayer fallback for cross-server /bal lookups. Handle null
  getName() for remotely resolved players.
- CrossServerMessenger: store UUID-to-name map from Velocity PLAYER_LIST
  messages with backward-compatible parsing (UUID+name and name-only
  formats). Broaden catch to Exception to prevent single parse failures
  from breaking the channel. Add getNetworkPlayerUuid() accessor.
- EzEconomyVelocity: send player UUID alongside username in
  broadcastPlayerList so Bukkit servers can resolve remote players.
- PaymentExecutor: check CrossServerMessenger network UUID map before
  falling back to storage.resolvePlayerByName.
- PayCommand: use messenger.getNetworkPlayerUuid for /pay * recipients
  and single /pay <player> resolution. Add debug logging for pay-all.
- plugin.yml: add ezpay/ezpayall aliases to avoid command conflicts.
- All language files (en, nl, es, fr, zh): add missing keys
  no_pending_payment, payment_confirm_required, payment_cancelled,
  unknown_conversion, usage_bank_create.
Version bump for the cross-server economy release including
/bal, /pay *, /payall cross-server support and Velocity UUID
broadcasting.
- README: add prerequisites table, MySQL setup example, store-on-join
  requirement, troubleshooting tips, and command alias note
- docs/configuration.md: expand store-on-join and cross-server sections
  with Velocity context, remove duplicate cross-server block
- config.yml: improve inline comments for store-on-join and cross-server
  to clarify Velocity network requirements
@ez-plugins ez-plugins closed this May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants