@@ -230,6 +230,7 @@ class LRUCache {
230230 #sizes;
231231 #starts;
232232 #ttls;
233+ #autopurgeTimers;
233234 #hasDispose;
234235 #hasFetchMethod;
235236 #hasDisposeAfter;
@@ -248,6 +249,7 @@ class LRUCache {
248249 // properties
249250 starts : c . #starts,
250251 ttls : c . #ttls,
252+ autopurgeTimers : c . #autopurgeTimers,
251253 sizes : c . #sizes,
252254 keyMap : c . #keyMap,
253255 keyList : c . #keyList,
@@ -349,13 +351,11 @@ class LRUCache {
349351 throw new TypeError ( 'sizeCalculation set to non-function' ) ;
350352 }
351353 }
352- if ( memoMethod !== undefined &&
353- typeof memoMethod !== 'function' ) {
354+ if ( memoMethod !== undefined && typeof memoMethod !== 'function' ) {
354355 throw new TypeError ( 'memoMethod must be a function if defined' ) ;
355356 }
356357 this . #memoMethod = memoMethod ;
357- if ( fetchMethod !== undefined &&
358- typeof fetchMethod !== 'function' ) {
358+ if ( fetchMethod !== undefined && typeof fetchMethod !== 'function' ) {
359359 throw new TypeError ( 'fetchMethod must be a function if specified' ) ;
360360 }
361361 this . #fetchMethod = fetchMethod ;
@@ -410,9 +410,7 @@ class LRUCache {
410410 this . updateAgeOnGet = ! ! updateAgeOnGet ;
411411 this . updateAgeOnHas = ! ! updateAgeOnHas ;
412412 this . ttlResolution =
413- isPosInt ( ttlResolution ) || ttlResolution === 0 ?
414- ttlResolution
415- : 1 ;
413+ isPosInt ( ttlResolution ) || ttlResolution === 0 ? ttlResolution : 1 ;
416414 this . ttlAutopurge = ! ! ttlAutopurge ;
417415 this . ttl = ttl || 0 ;
418416 if ( this . ttl ) {
@@ -447,10 +445,21 @@ class LRUCache {
447445 const starts = new ZeroArray ( this . #max) ;
448446 this . #ttls = ttls ;
449447 this . #starts = starts ;
448+ const purgeTimers = this . ttlAutopurge ?
449+ new Array ( this . #max)
450+ : undefined ;
451+ this . #autopurgeTimers = purgeTimers ;
450452 this . #setItemTTL = ( index , ttl , start = this . #perf. now ( ) ) => {
451453 starts [ index ] = ttl !== 0 ? start : 0 ;
452454 ttls [ index ] = ttl ;
453- if ( ttl !== 0 && this . ttlAutopurge ) {
455+ // clear out the purge timer if we're setting TTL to 0, and
456+ // previously had a ttl purge timer running, so it doesn't
457+ // fire unnecessarily.
458+ if ( purgeTimers ?. [ index ] ) {
459+ clearTimeout ( purgeTimers [ index ] ) ;
460+ purgeTimers [ index ] = undefined ;
461+ }
462+ if ( ttl !== 0 && purgeTimers ) {
454463 const t = setTimeout ( ( ) => {
455464 if ( this . #isStale( index ) ) {
456465 this . #delete( this . #keyList[ index ] , 'expire' ) ;
@@ -462,6 +471,7 @@ class LRUCache {
462471 t . unref ( ) ;
463472 }
464473 /* c8 ignore stop */
474+ purgeTimers [ index ] = t ;
465475 }
466476 } ;
467477 this . #updateItemAge = index => {
@@ -653,8 +663,7 @@ class LRUCache {
653663 * keys ( ) {
654664 for ( const i of this . #indexes( ) ) {
655665 const k = this . #keyList[ i ] ;
656- if ( k !== undefined &&
657- ! this . #isBackgroundFetch( this . #valList[ i ] ) ) {
666+ if ( k !== undefined && ! this . #isBackgroundFetch( this . #valList[ i ] ) ) {
658667 yield k ;
659668 }
660669 }
@@ -668,8 +677,7 @@ class LRUCache {
668677 * rkeys ( ) {
669678 for ( const i of this . #rindexes( ) ) {
670679 const k = this . #keyList[ i ] ;
671- if ( k !== undefined &&
672- ! this . #isBackgroundFetch( this . #valList[ i ] ) ) {
680+ if ( k !== undefined && ! this . #isBackgroundFetch( this . #valList[ i ] ) ) {
673681 yield k ;
674682 }
675683 }
@@ -681,8 +689,7 @@ class LRUCache {
681689 * values ( ) {
682690 for ( const i of this . #indexes( ) ) {
683691 const v = this . #valList[ i ] ;
684- if ( v !== undefined &&
685- ! this . #isBackgroundFetch( this . #valList[ i ] ) ) {
692+ if ( v !== undefined && ! this . #isBackgroundFetch( this . #valList[ i ] ) ) {
686693 yield this . #valList[ i ] ;
687694 }
688695 }
@@ -696,8 +703,7 @@ class LRUCache {
696703 * rvalues ( ) {
697704 for ( const i of this . #rindexes( ) ) {
698705 const v = this . #valList[ i ] ;
699- if ( v !== undefined &&
700- ! this . #isBackgroundFetch( this . #valList[ i ] ) ) {
706+ if ( v !== undefined && ! this . #isBackgroundFetch( this . #valList[ i ] ) ) {
701707 yield this . #valList[ i ] ;
702708 }
703709 }
@@ -1055,6 +1061,10 @@ class LRUCache {
10551061 }
10561062 }
10571063 this . #removeItemSize( head ) ;
1064+ if ( this . #autopurgeTimers?. [ head ] ) {
1065+ clearTimeout ( this . #autopurgeTimers[ head ] ) ;
1066+ this . #autopurgeTimers[ head ] = undefined ;
1067+ }
10581068 // if we aren't about to use the index, then null these out
10591069 if ( free ) {
10601070 this . #keyList[ head ] = undefined ;
@@ -1127,8 +1137,7 @@ class LRUCache {
11271137 peek ( k , peekOptions = { } ) {
11281138 const { allowStale = this . allowStale } = peekOptions ;
11291139 const index = this . #keyMap. get ( k ) ;
1130- if ( index === undefined ||
1131- ( ! allowStale && this . #isStale( index ) ) ) {
1140+ if ( index === undefined || ( ! allowStale && this . #isStale( index ) ) ) {
11321141 return ;
11331142 }
11341143 const v = this . #valList[ index ] ;
@@ -1174,7 +1183,7 @@ class LRUCache {
11741183 // cache and ignore the abort, or if it's still pending on this specific
11751184 // background request, then write it to the cache.
11761185 const vl = this . #valList[ index ] ;
1177- if ( vl === p || ignoreAbort && updateCache && vl === undefined ) {
1186+ if ( vl === p || ( ignoreAbort && updateCache && vl === undefined ) ) {
11781187 if ( v === undefined ) {
11791188 if ( bf . __staleWhileFetching !== undefined ) {
11801189 this . #valList[ index ] = bf . __staleWhileFetching ;
@@ -1238,8 +1247,7 @@ class LRUCache {
12381247 // defer check until we are actually aborting,
12391248 // so fetchMethod can override.
12401249 ac . signal . addEventListener ( 'abort' , ( ) => {
1241- if ( ! options . ignoreFetchAbort ||
1242- options . allowStaleOnFetchAbort ) {
1250+ if ( ! options . ignoreFetchAbort || options . allowStaleOnFetchAbort ) {
12431251 res ( undefined ) ;
12441252 // when it eventually resolves, update the cache.
12451253 if ( options . allowStaleOnFetchAbort ) {
@@ -1471,6 +1479,10 @@ class LRUCache {
14711479 if ( this . #size !== 0 ) {
14721480 const index = this . #keyMap. get ( k ) ;
14731481 if ( index !== undefined ) {
1482+ if ( this . #autopurgeTimers?. [ index ] ) {
1483+ clearTimeout ( this . #autopurgeTimers?. [ index ] ) ;
1484+ this . #autopurgeTimers[ index ] = undefined ;
1485+ }
14741486 deleted = true ;
14751487 if ( this . #size === 1 ) {
14761488 this . #clear( reason ) ;
@@ -1546,6 +1558,11 @@ class LRUCache {
15461558 if ( this . #ttls && this . #starts) {
15471559 this . #ttls. fill ( 0 ) ;
15481560 this . #starts. fill ( 0 ) ;
1561+ for ( const t of this . #autopurgeTimers ?? [ ] ) {
1562+ if ( t !== undefined )
1563+ clearTimeout ( t ) ;
1564+ }
1565+ this . #autopurgeTimers?. fill ( undefined ) ;
15491566 }
15501567 if ( this . #sizes) {
15511568 this . #sizes. fill ( 0 ) ;
0 commit comments