Skip to content

fix(cost): charge NAV_BUILD past the nav-cache short-circuit - #37000

Merged
sfreudenthaler merged 2 commits into
mainfrom
issue-36977-navtool-cache-pricing
Aug 11, 2026
Merged

fix(cost): charge NAV_BUILD past the nav-cache short-circuit#37000
sfreudenthaler merged 2 commits into
mainfrom
issue-36977-navtool-cache-pricing

Conversation

@wezell

@wezell wezell commented Aug 11, 2026

Copy link
Copy Markdown
Member

Proposed Changes

Follow-up to #36978, addressing a review finding that landed after merge: @RequestCost(Price.NAV_BUILD) on NavTool.getNav fired on method entry, so a live-mode navigation served entirely from NavToolCache still paid the full NAV_BUILD(10) — the common case on live traffic.

This moves the charge to a direct RequestCostHandler.incrementCost call on the cache-miss/build path, matching the cache-aware placement deliberately used in DotDirective.render and VelocityLiveMode.writePage:

  • Warm nav (live-mode cache hit): costs 0 — caching visibly pays off, consistent with cached containers/pages.
  • Cache miss / edit / preview: flat NAV_BUILD(10) — covers the folder/menu-item walk (findMenuItems, findSubFolders, IdentifierAPI.find), which is not metered anywhere else.
  • Content-backed menu items still stack their own CONTENT_FROM_CACHE/CONTENT_FROM_DB charges through the content factory — that stacking is intended and documented in the code comment.

Related to #36977.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VTt9ymEwfmHV9DSKe1vPuJ

This PR fixes: #36977

This PR fixes: #36977

The @RequestCost annotation on getNav fired on method entry, so a live-mode
navigation served entirely from NavToolCache still paid the full NAV_BUILD(10).
That contradicts the cache-aware placement used in DotDirective.render and
VelocityLiveMode.writePage, where cached work stays cheap. Move the charge to a
direct RequestCostHandler call on the cache-miss/build path: a warm nav now
costs 0 and only the folder/menu-item walk pays the flat build fee. Content-
backed menu items keep stacking their own content charges - that is intended.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VTt9ymEwfmHV9DSKe1vPuJ
@claude

claude Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Claude finished @sfreudenthaler's task in 1m 18s —— View job


PR Review: charge NAV_BUILD past the nav-cache short-circuit

  • Read the diff and both changed files
  • Verify charge placement, control flow, and import cleanup
  • Post review

I reviewed RequestCostHandler.java and NavTool.java against the base of #36978.

New Issues

No issues found.

The change is correct and consistent with the stated intent:

  • Charge placement (NavTool.java:127) sits after the live-mode cache short-circuit (NavTool.java:114-119), so a warm live-mode nav returns at line 117 and pays 0 — matching the DotDirective.render / VelocityLiveMode.writePage idiom now documented in RequestCostHandler's Javadoc.
  • Failure isolation is preserved: the direct call uses the incrementCost(Price, Class, String, Object[]) overload, which wraps the API call in try/catch (Throwable) and only logs — metering cannot take down nav rendering. Good choice over an inline APILocator.getRequestCostAPI() call.
  • Import cleanup is complete: @RequestCost had no other use in NavTool (only occurrence was the removed annotation), so swapping the import to RequestCostHandler leaves no dangling reference.
  • No new double-charge: the annotation previously fired once per getNav(host, path, languageId, user) entry; the direct call also fires once per build-path execution. The only behavioral deltas are the two intended ones — cache hits and the null-folder early return (NavTool.java:103-105) no longer charge. Not charging when no build work happens is the correct outcome.
  • Content-item stacking (CONTENT_FROM_CACHE/CONTENT_FROM_DB via the content factory) is unaffected and, as the comment notes, intentional.

Minor, non-blocking observations (not defects):

  • The method name is hardcoded as "getNav" in the args to incrementCost — this matches the convention at the sibling direct-charge sites and is only used for the HTML accounting report, so it's fine.
  • The Javadoc's "if a fourth site shows up, promote this to a real helper" note is a good guardrail against the copy-paste comment proliferating.

· issue-36977-navtool-cache-pricing

…andler

Addresses review feedback on #37000: point maintainers at the shared
convention behind NavTool.getNav, DotDirective.render and
VelocityLiveMode.writePage before a fourth copy of the comment appears.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Dbp268ibhwu3NavqzrVPg
@sfreudenthaler

Copy link
Copy Markdown
Member

Added a pointer for the cache-short-circuit charge idiom on RequestCostHandler's class javadoc — it's the one file all three direct-charge sites (NavTool.getNav, DotDirective.render, VelocityLiveMode.writePage) already call through, so it's where both a human and a future Claude session land before adding a fourth. 9e9a35a

@sfreudenthaler sfreudenthaler left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

good catch on review. Added a note as well so hopefully humans and bots find it before a reviewer needs to point it out in the future

@sfreudenthaler
sfreudenthaler added this pull request to the merge queue Aug 11, 2026
Merged via the queue into main with commit 17c8c54 Aug 11, 2026
67 checks passed
@sfreudenthaler
sfreudenthaler deleted the issue-36977-navtool-cache-pricing branch August 11, 2026 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area : Backend PR changes Java/Maven backend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Fix RequestCost instrumentation gaps and re-base the price table on resource-time

2 participants