You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
review remediation: URLFor controller/action route lookup — application-scope cache with negative caching and reload invalidation #2955
URLFor's controller/action-to-route lookup is an O(routes) scan memoized in a cache created fresh per request, with no negative caching. Line numbers verified against origin/develop @ 8971094.
vendor/wheels/Global.cfc:1535-1551 does the lookup; the memo is created fresh per request (Global.cfc ~2155) and is written only on a match. So a no-match — guaranteed for [controller]-pattern wildcard apps, since $addRoute deletes the controller key (Mapper.cfc:137-139) — re-runs the full route scan for every link-helper call: O(links × routes) per request.
Impact
Apps using the wildcard [controller] route pattern (a common setup) pay a full route-table scan for every linkTo/urlFor/redirectTo call, every request. The cost scales with both the number of links rendered and the route-table size.
Suggested approach
Moving the memo from request scope to application scope requires an invalidation story tied to route reloads:
Negative-cache lookup misses (not just matches).
Move the memo to application scope, cleared in $lockedLoadRoutes. Note: test specs manipulate routes without going through $lockedLoadRoutes, so add invalidation beyond it (related: the staticRoutes invalidation work in R18, which is already packaged).
Benchmark the URL-generation hot path before/after.
Acceptance criteria
Lookup misses are negative-cached; a [controller]-wildcard app does not re-scan per link helper.
Memo lives in application scope and is invalidated on route reload AND on test-spec route manipulation.
No stale-route regressions across the URL-generation specs.
Benchmark recorded for a representative wildcard-route app.
router — vendor/wheels/Global.cfc (URLFor lookup, ~lines 1535–1551 and the per-request memo near ~2155) and vendor/wheels/Mapper.cfc (route table mechanics, $addRoute ~137–139). No dedicated .ai/wheels/router/ doc exists yet; canonical routing reference lives in CLAUDE.md § "Routing Quick Reference" and the source itself.
Fix sketch
Promote the controller/action → route memo from request scope to application scope so it survives across requests. Add negative caching so misses (guaranteed for [controller]-wildcard apps, since $addRoute strips the controller key) don't re-scan on every link helper. Invalidate on route reload — $lockedLoadRoutes is the obvious hook, but test specs mutate routes outside that path, so invalidation must also fire on direct mutation (mirroring the staticRoutes invalidation already shipped in R18). Touch points likely include Global.cfc (URLFor), Mapper.cfc (mutation entry points / load), and possibly a small cache helper. Benchmark the URL-generation hot path before/after.
Confidence: medium
Bug and target code are unambiguous, but the fix is multi-file with real design choices (cache shape, invalidation strategy for non-reload mutations) and stale-route regression risk in the URL-generation specs.
A human review is required before merge. Reviewer A and Reviewer B will weigh in shortly. Doc updates (MDX guides, .ai/wheels/, CLAUDE.md) are handled separately by bot-update-docs.yml.
Activity
wheels-bot commentedon Jun 10, 2026
Wheels Bot — Triage
Classified as bug.
Suspected layer
router—vendor/wheels/Global.cfc(URLForlookup, ~lines 1535–1551 and the per-request memo near ~2155) andvendor/wheels/Mapper.cfc(route table mechanics,$addRoute~137–139). No dedicated.ai/wheels/router/doc exists yet; canonical routing reference lives inCLAUDE.md§ "Routing Quick Reference" and the source itself.Fix sketch
Promote the controller/action → route memo from request scope to application scope so it survives across requests. Add negative caching so misses (guaranteed for
[controller]-wildcard apps, since$addRoutestrips thecontrollerkey) don't re-scan on every link helper. Invalidate on route reload —$lockedLoadRoutesis the obvious hook, but test specs mutate routes outside that path, so invalidation must also fire on direct mutation (mirroring thestaticRoutesinvalidation already shipped in R18). Touch points likely includeGlobal.cfc(URLFor),Mapper.cfc(mutation entry points / load), and possibly a small cache helper. Benchmark the URL-generation hot path before/after.Confidence:
mediumBug and target code are unambiguous, but the fix is multi-file with real design choices (cache shape, invalidation strategy for non-reload mutations) and stale-route regression risk in the URL-generation specs.
<!-- wheels-bot:triage:2955 -->
<!-- wheels-bot:triage-class:bug -->
<!-- wheels-bot:triage-confidence:medium -->
wheels-bot commentedon Jun 10, 2026
Wheels Bot — Fix proposed
Draft PR: #2965
Spec:
vendor/wheels/tests/specs/global/urlforSpec.cfc— failing → passing (new describe block: app-scope memo presence, negative-cache on miss,$addRouteinvalidation,$lockedLoadRoutesinvalidation)Implementation:
vendor/wheels/Global.cfc(URLFor lookup +$lockedLoadRoutesclear),vendor/wheels/Mapper.cfc($addRouteclear)A human review is required before merge. Reviewer A and Reviewer B will weigh in shortly. Doc updates (MDX guides,
.ai/wheels/,CLAUDE.md) are handled separately bybot-update-docs.yml.Merge origin/develop into fix/bot-2963-roadmap-high-impact-cli-mcp-to…