Skip to content

review remediation: URLFor controller/action route lookup — application-scope cache with negative caching and reload invalidation #2955

Closed

Description

@bpamiri

Problem

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.

Source

Internal multi-agent framework review 2026-06-09, wave 2 (issues phase). Findings: dispatch-core DC17, routing R14.

Activity

  1. wheels-bot commented on Jun 10, 2026

    @wheels-bot
    Contributor

    Wheels Bot — Triage

    Classified as bug.

    Suspected layer

    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.

    <!-- wheels-bot:triage:2955 -->
    <!-- wheels-bot:triage-class:bug -->
    <!-- wheels-bot:triage-confidence:medium -->

  2. wheels-bot commented on Jun 10, 2026

    @wheels-bot
    Contributor

    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, $addRoute invalidation, $lockedLoadRoutes invalidation)
    Implementation: vendor/wheels/Global.cfc (URLFor lookup + $lockedLoadRoutes clear), vendor/wheels/Mapper.cfc ($addRoute clear)

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions