parse-community / parse-community/parse-server

Per-entry cache TTL is silently ignored by the in-memory cache adapter

Open
#10,630 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
21.4k
Forks
4.8k
Avg merge
7h 45m
Merged PRs (30d)
11

Description

New Issue Checklist
Issue Description

LRUCache#put passes the per-entry TTL to lru-cache as a positional number, but lru-cache v11 takes it as a property of an options object. The number is silently ignored and the entry falls back to the cache-wide cacheTTL, so on the default in-memory adapter a per-entry TTL cannot be set at all.

// src/Adapters/Cache/LRUCache.js
put(key, value, ttl = this.ttl) {
  this.cache.set(key, value, ttl);   // v11 signature is set(key, value, { ttl })
}

LRUCache#set in v11 destructures its third argument, so a number contributes no properties and ttl resolves to the instance default set in the constructor.

Two related defects in the same path:

  1. The LRUCache constructor never assigns this.ttl, so the ttl = this.ttl default in put is always undefined.
  2. SubCache accepts a ttl in its constructor and stores it, but put() ignores this.ttl and forwards only the caller's argument. CacheController constructs all three sub-caches (role, user, graphQL) without a TTL anyway, so the parameter is unused.

The one caller in Parse Server that requests a per-entry TTL is ParseGraphQLController, which caches the GraphQL config for 60 seconds:

// src/Controllers/ParseGraphQLController.js
return this.cacheController.graphQL.put(this.configCacheKey, graphQLConfig, 60000);

On the in-memory adapter that entry actually lives for cacheTTL (5000ms by default), so the config is re-read from the database roughly 12 times more often than intended. RedisCacheAdapter#put honors the TTL correctly via PX, so the same call behaves differently depending on the configured cache adapter.

Steps to reproduce

Against lru-cache 11.2.7 as vendored:

const { LRUCache } = require('lru-cache');
const cache = new LRUCache({ max: 10, ttl: 5000 });   // cacheTTL default

cache.set('a', 1, 60000);          // what LRUCache#put does today
cache.set('b', 1, { ttl: 60000 }); // v11 signature

console.log(cache.getRemainingTTL('a')); // 5000
console.log(cache.getRemainingTTL('b')); // 60000

Equivalently, through Parse Server: start a server with the default cache adapter, call config.cacheController.graphQL.put('k', 'v', 60000), wait longer than cacheTTL but less than 60 seconds, and get('k') returns null.

Actual Outcome

The per-entry TTL is discarded. Entries expire after the cache-wide cacheTTL.

Expected Outcome

The per-entry TTL is applied. A put with an explicit TTL keeps the entry for that duration, matching RedisCacheAdapter and the documented intent of the third parameter.

Environment

Server

  • Parse Server version: 9.10.1-alpha.6
  • Operating system: macOS 15.5
  • Local or remote host: local

Database

  • System (MongoDB or Postgres): MongoDB
  • Database version: 8.0
  • Local or remote host: local

Client

  • SDK (iOS, Android, JavaScript, PHP, Unity, etc): not applicable, server-internal cache
  • SDK version: not applicable
Logs

No error is produced. The TTL is dropped silently.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/Adapters/Cache/LRUCache.js and compare its put path with RedisCacheAdapter#put and the lru-cache v11 signature. Trace the 60000ms call in src/Controllers/ParseGraphQLController.js and the SubCache and CacheController construction described in the issue. Done means explicit per-entry TTLs work in the in-memory adapter, default and sub-cache TTL behavior is consistent, and the GraphQL cache no longer expires at cacheTTL.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, javascript, node.js
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.