fix: Per-entry cache TTL is ignored by the in-memory cache adapter - #10671
Conversation
|
🚀 Thanks for opening this pull request! We appreciate your effort in improving the project. Please let us know once your pull request is ready for review. Tip
Note Please respond to review comments from AI agents just like you would to comments from a human reviewer. Let the reviewer resolve their own comments, unless they have reviewed and accepted your commit, or agreed with your explanation for why the feedback was incorrect. Caution Pull requests must be written using an AI agent with human supervision. Pull requests written entirely by a human will likely be rejected, because of lower code quality, higher review effort and the higher risk of introducing bugs. Please note that AI review comments on this pull request alone do not satisfy this requirement. Our CI and AI review are safeguards, not development tools. If many issues are flagged, rethink your development approach. Invest more effort in planning and design rather than using review cycles to fix low-quality code. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Essentials Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review. 📝 WalkthroughWalkthroughThe PR upgrades ChangesLRU Cache TTL Handling
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Severity of issue fixed: Medium Merge Risk: ⚪ Minimal · up to The changed cache TTL handling matches the upgraded library’s API, and no actionable merge risk is established. Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (5 passed)
Full details: Linked Issues checkExplanation [ Full details: Engage In Review FeedbackExplanation The supplied current review has zero actionable findings. It also states that this does not establish whether earlier posted review comments are absent or resolved. The repository contains no review-thread metadata; the PR refs provide code changes only. Therefore, the available evidence cannot show whether the author engaged with all review feedback. Resolution Provide the full PR review discussion history, including earlier feedback comments, replies, and each comment's resolution state. Then verify that every item of feedback was discussed and either implemented in a commit or withdrawn by its reviewer.
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## alpha #10671 +/- ##
=======================================
Coverage 93.82% 93.82%
=======================================
Files 192 192
Lines 16875 16882 +7
Branches 252 252
=======================================
+ Hits 15833 15840 +7
Misses 1020 1020
Partials 22 22 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
46ecb8f to
14ed717
Compare
14ed717 to
408303a
Compare
## [9.10.1-alpha.16](9.10.1-alpha.15...9.10.1-alpha.16) (2026-09-22) ### Bug Fixes * Per-entry cache TTL is ignored by the in-memory cache adapter ([#10671](#10671)) ([1352c67](1352c67))
|
🎉 This change has been released in version 9.10.1-alpha.16 |
## [9.10.1](9.10.0...9.10.1) (2026-09-24) ### Bug Fixes * `Parse.Query.explain` runs afterFind trigger on query plan results ([#10536](#10536)) ([64d58ff](64d58ff)) * Account takeover via empty password in LDAP auth adapter ([GHSA-863r-39r9-vfcf](GHSA-863r-39r9-vfcf)) ([#10642](#10642)) ([f261957](f261957)) * Bump @parse/push-adapter from 8.4.0 to 8.5.3 ([#10676](#10676)) ([ae167c4](ae167c4)) * Bump body-parser from 2.2.2 to 2.3.0 ([#10600](#10600)) ([77e955f](77e955f)) * Bump express-rate-limit from 8.3.1 to 8.7.0 ([#10672](#10672)) ([73d8600](73d8600)) * Bump follow-redirects from 1.15.11 to 1.16.0 ([#10577](#10577)) ([d577327](d577327)) * Bump parse from 8.6.0 to 8.6.2, @parse/push-adapter from 8.5.3 to 8.5.5 and ws from 8.21.0 to 8.21.3 ([#10688](#10688)) ([11c8a40](11c8a40)) * Bump qs from 6.15.2 to 6.16.0 ([#10651](#10651)) ([25263e7](25263e7)) * Bump undici from 7.28.0 to 7.29.1 ([#10674](#10674)) ([2f09a30](2f09a30)) * Bump ws from 8.20.0 to 8.21.0 ([#10576](#10576)) ([629426f](629426f)) * Creating a session can delete another user's session ([#10582](#10582)) ([0df8779](0df8779)) * GraphQL argument and enum validation errors disclose target class names when public introspection is disabled ([GHSA-6m77-f8xr-f723](GHSA-6m77-f8xr-f723)) ([#10665](#10665)) ([fead3db](fead3db)) * GraphQL schema is disclosed by replaying an automatic persisted query when public introspection is disabled ([GHSA-gxxq-pghq-9vrc](GHSA-gxxq-pghq-9vrc)) ([#10669](#10669)) ([8d22053](8d22053)) * Install the latest Parse Server version in bootstrap.sh ([#10556](#10556)) ([997ee15](997ee15)) * LiveQuery discloses protected fields by resolving an incomplete subscriber identity ([GHSA-9jpp-xhh6-75mf](GHSA-9jpp-xhh6-75mf)) ([#10654](#10654)) ([66c507b](66c507b)) * Per-entry cache TTL is ignored by the in-memory cache adapter ([#10671](#10671)) ([1352c67](1352c67)) * Rate limit is bypassed by sending request header `X-Forwarded-For: 127.0.0.1` when Parse Server option `trustProxy` is permissive ([#10664](#10664)) ([ebd425e](ebd425e)) * Relation count query bypasses protectedFields for identity-scoped groups ([GHSA-rmhf-xv62-rm99](GHSA-rmhf-xv62-rm99)) ([#10667](#10667)) ([a32977f](a32977f)) * Server crash from unhandled promise rejection when multiple Cloud Code validator fields fail ([#10540](#10540)) ([90c2778](90c2778)) * Unauthenticated deletion of installation records via operator injection in device token deduplication ([GHSA-cc6h-c8m4-hgrx](GHSA-cc6h-c8m4-hgrx)) ([#10657](#10657)) ([ad00f82](ad00f82)) * Unverified auth provider identity accepted on password login for code-based auth adapters ([GHSA-mr43-w6c2-mvjq](GHSA-mr43-w6c2-mvjq)) ([#10662](#10662)) ([9b73e6f](9b73e6f))
|
🎉 This change has been released in version 9.10.1 |
Issue
Two related defects in the in-memory cache adapter, plus the
lru-cacheupgrade that makes one of them fatal.1. Per-entry TTL has never been applied.
LRUCache.put()passedttlaslru-cache's third positional argument, but that slot is an options object. Destructuring a number yieldsundefinedfor every option, so the per-entry TTL was silently discarded and the cache-wide TTL always won. Verified on the currently pinned11.2.7:The practical effect is that
RedisCacheAdapterhonours per-entry TTLs whileInMemoryCacheAdapterignores them, so the two adapters disagree. For exampleParseGraphQLControllercaches its config withput(configCacheKey, graphQLConfig, 60000)but in-memory it actually expires aftercacheTTL(5s by default).2.
this.ttlwas never assigned. The default parameterput(key, value, ttl = this.ttl)read a property the constructor never set, so it was alwaysundefined.3.
lru-cache@11.3.0turns defect 1 into a hard failure. In an undocumented change (absent from the upstream CHANGELOG),set(),get(),has(),peek(),fetch(),forceFetch()andmemo()now write back onto the caller-supplied options object:Passing a non-object therefore throws. Bisected:
11.2.7OK,11.3.0–11.5.3throwTypeError: Cannot create property 'status' on number '60000'. This is why the Dependabot bump (#10596) fails every CI job.Two call sites passed a positional number, both on default code paths:
src/Adapters/Cache/LRUCache.js— reached fromParseGraphQLController._putCachedGraphQLConfigthrough the defaultInMemoryCacheAdapter.src/LiveQuery/ParseLiveQueryServer.ts— the invalid-session-token negative cache, which fires whenever a LiveQuery client presents anINVALID_SESSION_TOKEN(the path covered by the spec for GHSA-2xm2-xj2q-qgpj).This PR supersedes #10632, whose
LRUCache.jsfix it adopts, and #10596.Closes #10596
Closes #10632
Approach
Fix both call sites to pass an options object, assign
this.ttlin the constructor, and bumplru-cacheto11.5.2.LRUCache.put()now maps the TTL explicitly:Infinity->0, which is howlru-cacheexpresses "never expires", matchingRedisCacheAdapter'sInfinityhandling.{ ttl }.undefined, which is howlru-cacheexpresses "use the cache-wide TTL".Infinityis deliberately not forwarded as-is. Node cannot express it as a timer duration: underttlAutopurgeit emitsTimeoutOverflowWarning: Infinity does not fit into a 32-bit signed integerand clamps the timer to 1ms, so the purge timer re-fires every millisecond.ParseLiveQueryServernow passes{ ttl: this.config.cacheTimeout }. That one is behaviour-preserving by construction:authCacheis built withttl: config.cacheTimeout, so the explicit value equals the cache-wide one.Behaviour change
Per-entry TTLs now take effect in the in-memory adapter. The most visible consequence is that the GraphQL config cache honours its intended
60000instead of falling back tocacheTTL(5s by default), bringing it in line with the Redis adapter.Breaking Changes
None.
Tests
Adds specs covering per-entry TTL longer than the cache TTL, shorter than the cache TTL,
Infinity, a non-numeric TTL, and an omitted TTL. Four of them fail against the unfixed adapter on11.5.2with the sameTypeErrorseen in CI, and all pass with the fix.Verified locally:
InMemoryCacheAdapter8/8,CacheController5/5,ParseGraphQLController25/25,ParseLiveQuery56/56, lint clean.Known adapter difference, not changed here
RedisCacheAdaptertreatsttl === 0as "do not cache at all" (it returns before writing), whereas the in-memory adapter treats0as "not a positive TTL" and falls back to the cache-wide value. This PR keeps the existing in-memory behaviour rather than widening scope; worth a follow-up if full parity is wanted.Tasks
spec/InMemoryCacheAdapter.spec.jsSummary by CodeRabbit
Bug Fixes
Maintenance