Skip to content

Harden status ping path and refresh prebuilt jar#8

Merged
ohnodev merged 4 commits intomainfrom
fix/status-ping-hardening
Apr 16, 2026
Merged

Harden status ping path and refresh prebuilt jar#8
ohnodev merged 4 commits intomainfrom
fix/status-ping-hardening

Conversation

@ohnodev
Copy link
Copy Markdown
Owner

@ohnodev ohnodev commented Apr 16, 2026

Summary

  • add a short-TTL cached status response path so repeated server-list pings avoid rebuilding remapped status payloads on every request
  • replace per-ping STATUS install INFO spam with sampled aggregate logging while keeping login/post-configuration visibility
  • refresh prebuilt/legacylink-0.1.1.jar from the updated status-hardening build

Test plan

  • Run ./gradlew build in legacylink
  • Deploy rebuilt legacylink-0.1.1.jar to minecraft-cabal/server/mods
  • Restart server and verify clean startup with LegacyLink ready logs
  • Manual in-game server-list refresh burst check for reduced STATUS log noise

Made with Cursor

Summary by CodeRabbit

  • Performance
    • Added centralized, short‑lived caching for legacy status responses to reuse prebuilt replies, reducing duplicate remapping and improving response times.
  • Reliability
    • Made status remapping consistent across pathways to avoid redundant work and ensure uniform responses.
  • Chores
    • Introduced rate‑limited installation/phase logging to reduce noisy log output while keeping diagnostics.

ohnodev added 2 commits April 16, 2026 13:48
Add a short-TTL (1s) cache for the remapped legacy status response in
both StatusPacketMixin and LegacyPacketHandler so repeated server-list
refreshes reuse a prebuilt packet instead of reconstructing each time.

Replace per-connection INFO logging for STATUS translator installs with
a sampled summary (every 10s with counts) to eliminate log flood from
rapid server-list polling without losing visibility.

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

📝 Walkthrough

Walkthrough

Adds a centralized short-lived (1s TTL) cache for remapped legacy ClientboundStatusResponsePackets via a new LegacyStatusCacheManager, converts remapStatusResponse to static and delegates remapping to the cache manager, and adds a synchronized, rate‑limited logStatusInstall() path that suppresses the usual install INFO log when phase == "status".

Changes

Cohort / File(s) Summary
Handler: static remap & rate-limited install logging
src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java
Made remapStatusResponse(...) private static and delegate remapping to the cache manager; added private static synchronized void logStatusInstall() plus static counters/timestamp to rate-limit INFO logs when phase == "status" (suppresses standard INFO for status installs).
Mixin: delegate status response to cache manager
src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java
Removed inline legacy remap logic; added a private helper that calls the centralized cache manager (getOrBuildCachedResponse(this.status)) and sends cached/built ClientboundStatusResponsePacket.
New: centralized status remap & short-lived cache
src/main/java/dev/ohno/legacylink/status/LegacyStatusCacheManager.java
Added LegacyStatusCacheManager with two cache scopes (listener vs outbound handler), 1s TTL, and public getOrBuildForStatusListener(...) / getOrBuildForOutboundHandler(...) entrypoints. Builds forced-legacy ServerStatus (protocol "26.1.2") and returns ClientboundStatusResponsePacket when cache miss or expired.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant StatusPacketMixin
    participant LegacyStatusCacheManager
    participant LegacyPacketHandler

    Client->>StatusPacketMixin: ServerboundStatusRequestPacket
    activate StatusPacketMixin
    StatusPacketMixin->>LegacyStatusCacheManager: getOrBuildForStatusListener(status)
    alt cache hit
        LegacyStatusCacheManager-->>StatusPacketMixin: cached ClientboundStatusResponsePacket
    else cache miss
        LegacyStatusCacheManager->>LegacyPacketHandler: (buildLegacyStatusResponse) remap & build legacy packet
        activate LegacyPacketHandler
        LegacyPacketHandler-->>LegacyStatusCacheManager: new ClientboundStatusResponsePacket
        deactivate LegacyPacketHandler
        LegacyStatusCacheManager-->>StatusPacketMixin: new ClientboundStatusResponsePacket
    end
    StatusPacketMixin->>Client: send ClientboundStatusResponsePacket
    StatusPacketMixin->>StatusPacketMixin: cancel original handler
    deactivate StatusPacketMixin
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I cached the hop of a status song,
One second hush then bounce along,
Counted installs with gentle pace,
Synchronized hops keep the log in place,
Legacy pings return with cheerful throng.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Harden status ping path and refresh prebuilt jar' accurately summarizes the main changes: it reflects the core work of hardening the status ping handling through caching/rate-limiting and the artifact refresh, which aligns with the PR objectives of adding TTL-cached status responses, reducing logging spam, and refreshing the prebuilt jar.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/status-ping-hardening

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java`:
- Around line 110-111: The STATUS log window is seeded at class init causing the
first post-quiescence ping to report a tiny interval; update the window start
when beginning a new sampling window by resetting statusInstallWindowStart =
System.nanoTime() at the moment statusInstallCount transitions from 0 to 1
(i.e., when incrementing statusInstallCount in LegacyPacketHandler), so the
elapsed interval reflects time since first sample rather than class load; apply
the same change to the analogous block that manages the other status window (the
code around the 228–240 region) to reinitialize its window start on its own 0→1
transition.
- Around line 112-113: Wrap cachedStatusResponse and statusCacheBuiltAt into a
single immutable holder (e.g. class StatusCache {
ClientboundStatusResponsePacket response; long builtAt; }) and replace the two
separate fields with one volatile reference (e.g. private static volatile
StatusCache statusCache). Update all reads to read the single volatile
statusCache and use its .response and .builtAt atomically, and update all writes
to construct a new StatusCache instance and assign it to the volatile reference
(instead of writing cachedStatusResponse and statusCacheBuiltAt separately).
Make changes in LegacyPacketHandler where cachedStatusResponse and
statusCacheBuiltAt are read/written so the publish is atomic and no
stale-response/new-timestamp mix can occur.

In `@src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java`:
- Around line 24-26: The three volatile fields cachedLegacyResponse,
cachedAtNanos, and cachedSourceStatus cause a race when read/written separately;
replace them with a single immutable holder class (e.g., LegacyStatusCache or
StatusCacheEntry) containing the ClientboundStatusResponsePacket, ServerStatus,
and timestamp, and publish that holder via one volatile reference (e.g.,
volatile LegacyStatusCache cachedStatus). Update all reads to read the single
volatile holder once and all writes to construct a new holder instance and
assign it to the volatile field (update any places that set
cachedLegacyResponse/cachedSourceStatus/cachedAtNanos to instead set the new
holder and adjust access sites to use holder.packet, holder.sourceStatus,
holder.timestamp).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 36ce1a4c-1caf-4289-8763-37654298d7e8

📥 Commits

Reviewing files that changed from the base of the PR and between 6b999c2 and 465324b.

⛔ Files ignored due to path filters (1)
  • prebuilt/legacylink-0.1.1.jar is excluded by !**/*.jar
📒 Files selected for processing (2)
  • src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java
  • src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java

Comment thread src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java Outdated
Comment thread src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java Outdated
Comment thread src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java (1)

56-75: Consider unifying this cache with LegacyPacketHandler’s status cache.

StatusPacketMixin and LegacyPacketHandler currently maintain separate 1-second caches with different keying rules (ServerStatus identity+TTL here vs TTL-only in src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java:568-586). A shared cache/remap utility would reduce drift and keep behavior consistent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java` around lines
56 - 75, The two separate 1s caches should be unified into a single shared cache
utility to avoid drift: extract the caching/remapping logic from
StatusPacketMixin.getOrBuildCachedResponse and the block in LegacyPacketHandler
into a new shared helper (e.g., LegacyStatusCacheManager) that owns the
LegacyStatusCache data and STATUS_CACHE_TTL_NS semantics; then have
StatusPacketMixin.getOrBuildCachedResponse and LegacyPacketHandler call that
helper to fetch or build the remapped ClientboundStatusResponsePacket, ensuring
both use the same keying/TTL rules and removing duplicate cache state from
StatusPacketMixin and LegacyPacketHandler.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java`:
- Around line 56-75: The two separate 1s caches should be unified into a single
shared cache utility to avoid drift: extract the caching/remapping logic from
StatusPacketMixin.getOrBuildCachedResponse and the block in LegacyPacketHandler
into a new shared helper (e.g., LegacyStatusCacheManager) that owns the
LegacyStatusCache data and STATUS_CACHE_TTL_NS semantics; then have
StatusPacketMixin.getOrBuildCachedResponse and LegacyPacketHandler call that
helper to fetch or build the remapped ClientboundStatusResponsePacket, ensuring
both use the same keying/TTL rules and removing duplicate cache state from
StatusPacketMixin and LegacyPacketHandler.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ddf6a3a0-88ee-4b85-92d3-ab1e761d999a

📥 Commits

Reviewing files that changed from the base of the PR and between 465324b and f0b1ba0.

⛔ Files ignored due to path filters (1)
  • prebuilt/legacylink-0.1.1.jar is excluded by !**/*.jar
📒 Files selected for processing (2)
  • src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java
  • src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java

Consolidate the mixin and outbound handler status remap caches so both paths use identical TTL and keying behavior from a single utility.

Made-with: Cursor
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/java/dev/ohno/legacylink/status/LegacyStatusCacheManager.java (1)

53-55: Optional: move the legacy version name to a constant.

Line 54 hardcodes "26.1.2" while Line 55 uses LegacyLinkConstants.PROTOCOL_26_1_2; extracting the string to constants as well would prevent accidental mismatches later.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/dev/ohno/legacylink/status/LegacyStatusCacheManager.java`
around lines 53 - 55, Extract the hardcoded legacy version string "26.1.2" into
a constant and use it when constructing ServerStatus.Version to avoid
mismatches; add a constant (e.g., LEGACY_VERSION_NAME = "26.1.2") near
LegacyLinkConstants or inside LegacyStatusCacheManager and replace the literal
in the ServerStatus.Version(...) call so both the version name and
LegacyLinkConstants.PROTOCOL_26_1_2 are defined from constants.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/main/java/dev/ohno/legacylink/status/LegacyStatusCacheManager.java`:
- Around line 53-55: Extract the hardcoded legacy version string "26.1.2" into a
constant and use it when constructing ServerStatus.Version to avoid mismatches;
add a constant (e.g., LEGACY_VERSION_NAME = "26.1.2") near LegacyLinkConstants
or inside LegacyStatusCacheManager and replace the literal in the
ServerStatus.Version(...) call so both the version name and
LegacyLinkConstants.PROTOCOL_26_1_2 are defined from constants.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2df52c31-6f0d-479f-8bad-4c8cc6a9163a

📥 Commits

Reviewing files that changed from the base of the PR and between f0b1ba0 and f81238c.

📒 Files selected for processing (3)
  • src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java
  • src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java
  • src/main/java/dev/ohno/legacylink/status/LegacyStatusCacheManager.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java

@ohnodev ohnodev merged commit e361c7c into main Apr 16, 2026
2 checks passed
@ohnodev ohnodev deleted the fix/status-ping-hardening branch April 16, 2026 07:42
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