Skip to content

fix(cache): observe action cache hits and keep appendToKey (B1–B2) - #3413

Merged
bpamiri merged 5 commits into
developfrom
cursor/cache-hardener-b1-b2-19f8
Aug 25, 2026
Merged

fix(cache): observe action cache hits and keep appendToKey (B1–B2)#3413
bpamiri merged 5 commits into
developfrom
cursor/cache-hardener-b1-b2-19f8

Conversation

@bpamiri

@bpamiri bpamiri commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Why

Cache hardener for BLOCKERs B1–B2 and SHOULDs S1–S9. Peter flipped S1/S2/S3/S6/S7/S8. S9 is in. Base is develop after #3412 (26f71776568c1360b12b3025f96479abbb009f61).

cacheFileChecking stays true. caches() still defaults time=60 / static=false when an action is named.

Scope

  • vendor/wheels/controller/caching.cfc — B2 first-match + appendToKey; S1 named actions; S6 body drop; S8 CompareNoCase
  • vendor/wheels/events/init/caching.cfm — S2 testing stays cache-off
  • vendor/wheels/global/cache.cfm — S3 session/user action key; S5 store lock; S7 targeted $clearCache(); S9 stored false is a hit; S6 action key index
  • vendor/wheels/tests/specs/caching/CacheHardenerSpec.cfc — Desk IDs B1–B2 / S1–S9
  • vendor/wheels/tests/specs/controller/cachingSpec.cfc — B1 write/hit/key; S1 no-action throw; $cacheSettingsForAction clears leftover dummy1 before caches(time=100) so first-match is not the earlier default time=60 row

Out of scope: CLI, ManifestCache, model query/schema cache, Global leftover S4 (catch swallow).

PROVEN

ID Status One line
B1 PROVEN cachingSpec and CacheHardenerSpec observe write, hit, and the session-qualified store key, not only processAction toBeTrue
B2 PROVEN $cacheSettingsForAction first-matches like processAction and keeps appendToKey. Not an ESCALATE: public caches() runtime stays first-match. cachingSpec now clears before the time=100 lookup so leftover dummy1 does not win
S1 PROVEN caches() / caches(static=true) with no action throws Wheels.InvalidArgument. Explicit caches(action="*") still allowed
S2 PROVEN cacheActions/Pages/Partials/Images/Queries enable only when environment is not development or testing
S3 PROVEN $actionCacheKey folds $sessionCacheIdentity() (session.user.id / session.user / sessionid) so alice/bob params-only pages do not leak
S4 PROVEN $addToCache still silent-drops when full after cull. Cull/drop policy unchanged
S5 PROVEN $addToCache / $getFromCache / $clearCache take exclusive wheelsCacheStore. add/get/clear values unchanged
S6 PROVEN clearCachableActions drops this controller's action bodies via cacheActionIndex. A decoy key for another controller stays
S7 PROVEN no-arg $clearCache() clears each category in place and keeps the main / action buckets. Parent StructClear(application.wheels.cache) is gone
S8 PROVEN caches("CachedShow") matches action cachedShow in $cacheSettingsForAction and processAction
S9 PROVEN $addToCache(key, false) then $getFromCache(key) returns false as a hit. A miss is only absent / expired / culled. $isCacheMiss() reads the last lookup, not the value. Missing keys still return false

Tradeoffs

B2 aligns the test getter to processAction first-match. That is not a public last-wins flip.

S3 suffixes only category=action store keys. Page/partial/query $hashedKey consumers are unchanged.

S6 indexes keys at $addToCache when variables.$class.name is present. No full-bucket wipe of every controller.

S9 returns the stored payload, including false. Public miss for an absent key is still false. Distinguish with $isCacheMiss() (last lookup). $doubleCheckedLock still treats a boolean-false return as a miss, so a cached boolean false will re-execute on the DCL path.

Blast Radius

Apps that called caches() with no action now get Wheels.InvalidArgument. Testing no longer enables action/page/partial/image/query caches at boot. Action cache entries are per session/user. $clearCache() no longer destroys category structs. Callers that stored boolean false and compared the get result with false must use $isCacheMiss() to tell a hit from a miss.

Verification

wheels test --core --ci --filter=caching
Scope: wheels.tests.specs.caching
21 passed, 0 failed, 0 error, 0 skipped
wheels test --core --ci --filter=controller
Scope: wheels.tests.specs.controller
552 passed, 0 failed, 0 error, 0 skipped

LuCLI 32796766018 failed cachingSpec “is getting cache settings for action” (Expected [100] but received [60]) because leftover dummy1 at default time=60 was first-match. That spec now calls $clearCachableActions() first. $cacheSettingsForAction stays first-match.

Lucee 7.0.0.395 / sqlite

HEAD

b9e209137815fd5a787ffdea6697b633ef35537c

Open in Web Open in Cursor 

cachingSpec only asserted processAction toBeTrue. $cacheSettingsForAction
last-wins and drops appendToKey, unlike processAction first-match.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Peter Amiri <peter@alurium.com>
$cacheSettingsForAction now breaks on the first match like processAction
and keeps appendToKey. $addToCache / $getFromCache / $clearCache take
wheelsCacheStore. Cull and silent-drop policy are unchanged.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Peter Amiri <peter@alurium.com>
@github-actions github-actions Bot added the docs label Aug 25, 2026
cursoragent and others added 3 commits August 25, 2026 01:11
caches() now requires named actions. testing stays cache-off.
Action keys include session/user. clearCachableActions drops bodies.
$clearCache() keeps category buckets. caches(Foo) matches foo.
Stored false is boxed so $getFromCache does not treat it as a miss.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Peter Amiri <peter@alurium.com>
$getFromCache must give back a stored falsey payload instead of
collapsing it into a miss. A miss is only an absent, expired, or
culled key. $isCacheMiss() now reads the last lookup, not the value.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Peter Amiri <peter@alurium.com>
B2 first-match returns the leftover default time=60 row that earlier
dummy specs leave on the controller class. Clear before caches() so
the time=100 row is the first match.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Peter Amiri <peter@alurium.com>
@bpamiri
bpamiri marked this pull request as ready for review August 25, 2026 01:25
@bpamiri
bpamiri merged commit c3147a5 into develop Aug 25, 2026
14 checks passed
@bpamiri
bpamiri deleted the cursor/cache-hardener-b1-b2-19f8 branch August 25, 2026 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants