Skip to content

fix(api): prevent shared MySQL getPoints() loading exceptions - #1740

Merged
BenCodez merged 4 commits into
masterfrom
fix/shared-mysql-getpoints-loading-fallback-20261031
Oct 31, 2026
Merged

BenCodez merged 4 commits into
masterfrom
fix/shared-mysql-getpoints-loading-fallback-20261031

Conversation

@BenCodez

@BenCodez BenCodez commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

Problem

EconomyShopGUI calls VotingPluginUser.getPoints() directly as an economy balance. With current AdvancedCore shared MySQL cache guards, a click on a player whose shared snapshot is not yet published throws IllegalStateException: Shared user data is still loading. VotingPlugin #1739 fixed the placeholder path, not the Java API. VotingPlugin 7.1.1 had the same getPoints() method, but its corresponding AdvancedCore version could synchronously fall through to a MySQL read.

Change

  • On Bukkit/Folia-owned threads with MySQL storage, make the existing getPoints() read a published, point-fenced snapshot. If unavailable (cold, invalidated, pending/uncertain debit), return the historical integer default 0 instead of throwing or blocking for SQL. A missing balance is not proof of an actual zero.
  • Add getPointsIfLoaded(): OptionalInt so new integrations can distinguish loading from genuine zero without unsafe default-value semantics.
  • Reuse the point-placeholder mutation fence; do not read stale or optimistic values during pending/uncertain debits.
  • Schedule existing deduplicated worker recovery on missing snapshots, preserving nonblocking platform calls.
  • Preserve normal storage and MySQL worker-thread read paths.
  • Document integration limitations: a legacy shop may reject the first click while the cache loads, but should not throw; spending still requires confirmed payment.

Verification

Added VotingPluginUserPointReadCompatibilityTest for cold cache, known zero, invalidated/partially published cache, pending mutation, malformed values, per-server point column, ordinary storage and worker reads.

Build/testing pending. This is a draft PR for CI validation and independent review. No local Maven build was possible in the connected environment, and the change has not been runtime-tested against EconomyShopGUI.

Important

No reversion of AdvancedCore's shared-storage protection and no synchronous JDBC on Bukkit/Paper/Folia-owned threads. Do not merge before CI and independent review verify the direct API and economy integration behavior.

Summary by CodeRabbit

  • New Features
    • Added a non-blocking way for integrations to check whether a point balance is available, while distinguishing a known zero balance from a balance that is still loading or uncertain.
    • Point reads on Bukkit/Folia-owned threads with MySQL storage now use published balances rather than performing a database read; unavailable values return zero.
  • Documentation
    • Added guidance for reading point balances and handling loading states. Clarified that displayed balances are advisory and purchases should rely on confirmed debits.

@coderabbitai

coderabbitai Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Caution

Review failed

The pull request is closed.

Walkthrough

The change adds getPointBalanceIfReady() and getPointsIfLoaded() for point balance reads. On Bukkit/Folia-owned threads with MySQL storage, getPoints() uses the published balance and returns 0 when it is unavailable. Tests and documentation describe these read states.

Changes: Point Balance Reads

Layer / File(s) Summary
Fence-aware point read API
VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/PlaceHolders.java, VotingPlugin/src/main/java/com/bencodez/votingplugin/user/VotingPluginUser.java, VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/user/VotingPluginUserPointReadCompatibilityTest.java, docs/point-shop-integrations.md
PlaceHolders.getPointBalanceIfReady() reads a published balance under the point fence and schedules recovery for recoverable states or missing snapshots. VotingPluginUser.getPointsIfLoaded() exposes an OptionalInt; getPoints() uses it on Bukkit/Folia-owned threads with MySQL storage. Tests cover unavailable, valid, malformed, and pending-mutation states. The documentation describes these APIs and their limits.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Thread as Bukkit/Folia thread
  participant User as VotingPluginUser
  participant Placeholders as PlaceHolders
  participant Fence as Point fence
  participant Snapshot as Published snapshot
  participant Recovery as Recovery worker
  Thread->>User: Call getPoints()
  User->>User: Call getPointsIfLoaded()
  User->>Placeholders: Call getPointBalanceIfReady(user)
  Placeholders->>Fence: Read fence state
  Placeholders->>Snapshot: Read published balance
  Placeholders->>Recovery: Schedule recovery when needed
  Placeholders-->>User: Return balance or empty result
  User-->>Thread: Return balance or zero
Loading

Possibly related PRs

Merge Risk: Moderate · up to 79bbd

The new fallback keeps getPoints() from throwing while a MySQL balance is loading. However, an exact-zero Points requirement can pass without a confirmed balance and may grant a reward. Make the built-in Points requirement reject an unloaded balance before merging.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@BenCodez
BenCodez marked this pull request as ready for review October 31, 2026 18:20
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-31T18:22:34.395723Z 79bbdb1 Draft marked ready
🔒 Security Review ⚠️ Failed 2026-10-31T18:20:57.353529Z
We couldn’t complete this review. Comment @codex security review to try again.
79bbdb1 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

The account paying for this security review has reached its Codex usage limits. The payer can check the Codex usage dashboard. For personal accounts, using credits requires enabling “Use credits for security reviews” in Code review settings. If you do not manage the paying account, contact this repository's admins.

@BenCodez
BenCodez merged commit e09fa0f into master Oct 31, 2026
5 of 6 checks passed
@BenCodez
BenCodez deleted the fix/shared-mysql-getpoints-loading-fallback-20261031 branch October 31, 2026 18:23
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.

1 participant