fix: reschedule autopurge timer when updateAgeOnGet resets TTL start#392
Closed
thekauer wants to merge 1 commit intoisaacs:mainfrom
Closed
fix: reschedule autopurge timer when updateAgeOnGet resets TTL start#392thekauer wants to merge 1 commit intoisaacs:mainfrom
thekauer wants to merge 1 commit intoisaacs:mainfrom
Conversation
When updateAgeOnGet (or updateAgeOnHas) resets the start time via #updateItemAge, the one-shot autopurge timer scheduled by #setItemTTL is not rescheduled. The timer fires at the original deadline, finds the entry non-stale (start was reset), does nothing, and no new timer is ever created -- making the entry immortal. Fix: reschedule the autopurge timer in #updateItemAge when one exists, following the same pattern as #setItemTTL.
Owner
|
Good find, thanks! I noticed that the method was functionally identical to the other code setting the ttlAutopurge timer, so abstracted them out, but to answer your question, yes, sending a test with a patch that fixes it is 100% correct and appropriate and much appreciated :) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I am not sure if this is the correct way to report this, but this is what I've found. Feel free to close this if this is inappropriate.
Bug
When using
updateAgeOnGet: truewithttlAutopurge: true, entries that are.get()'d at least once become permanently stuck in the cache. The autopurge timer fires but finds the entry "not stale" (becauseupdateAgeOnGetreset the start time), and no replacement timer is ever scheduled.Reproduction
Output:
Root cause
#setItemTTL(called on.set()) is the only place that schedules an autopurge timer.#updateItemAge(called on.get()whenupdateAgeOnGet: true) only resets the start time without rescheduling the timer:The sequence:
.set('A')at t=0 - schedulessetTimeout(fn, 2001).get('A')at t=500ms -starts[0] = now(), no timer changenow() - starts[0]= ~1500ms < 2000ms, not stale, does nothingFix
Reschedule the autopurge timer in
#updateItemAgewhen one exists, following the same pattern as#setItemTTL. The fix only activates when all three conditions are true:ttlAutopurge: true(autopurge timers exist)updateAgeOnGet: trueorupdateAgeOnHas: true(age is being updated).set()with a TTL (timer exists for that index)All 17,670 existing tests pass with this change. Two new test cases are included.
Impact
We discovered this in production where ~160 connection pool objects were permanently stuck in an LRU cache despite a 10-minute TTL, causing ~1.5Gi of unreclaimable native memory per Node.js process.
Workaround
Use
.set(key, existingValue)instead of relying onupdateAgeOnGet, which properly calls#setItemTTLand reschedules the timer. SetnoDisposeOnSet: trueto prevent the dispose callback from firing on re-set.Version
lru-cache 11.2.4 (also verified on 11.2.6)