@@ -929,6 +929,21 @@ export namespace LRUCache {
929929 */
930930 maxSize ?: Size
931931
932+ /**
933+ * The effective size for background fetch promises.
934+ *
935+ * This has no effect unless `maxSize` and `sizeCalculation` are used,
936+ * and a {@link LRUCache.OptionsBase.fetchMethod} is provided to
937+ * support {@link LRUCache#fetch}.
938+ *
939+ * If a stale value is present in the cache, then the effective size of
940+ * the background fetch is the size of the stale item it will eventually
941+ * replace. If not, then this value is used as its effective size.
942+ *
943+ * @default 1
944+ */
945+ backgroundFetchSize ?: number
946+
932947 /**
933948 * The maximum allowed size for any single item in the cache.
934949 *
@@ -1274,6 +1289,9 @@ export class LRUCache<K extends {}, V extends {}, FC = unknown> {
12741289 */
12751290 ignoreFetchAbort : boolean
12761291
1292+ /** {@link LRUCache.OptionsBase.backgroundFetchSize } */
1293+ backgroundFetchSize : number
1294+
12771295 // computed properties
12781296 #size: LRUCache . Count
12791297 #calculatedSize: LRUCache . Size
@@ -1428,9 +1446,12 @@ export class LRUCache<K extends {}, V extends {}, FC = unknown> {
14281446 allowStaleOnFetchRejection,
14291447 allowStaleOnFetchAbort,
14301448 ignoreFetchAbort,
1449+ backgroundFetchSize = 1 ,
14311450 perf,
14321451 } = options
14331452
1453+ this . backgroundFetchSize = backgroundFetchSize
1454+
14341455 if ( perf !== undefined ) {
14351456 if ( typeof perf ?. now !== 'function' ) {
14361457 throw new TypeError (
@@ -1707,12 +1728,15 @@ export class LRUCache<K extends {}, V extends {}, FC = unknown> {
17071728 sizes [ index ] = 0
17081729 }
17091730 this . #requireSize = ( k , v , size , sizeCalculation ) => {
1710- // provisionally accept background fetches.
1711- // actual value size will be checked when they return.
1712- if ( this . #isBackgroundFetch( v ) ) {
1713- return 0
1714- }
17151731 if ( ! isPosInt ( size ) ) {
1732+ // provisionally accept background fetches.
1733+ // actual value size will be checked when they return.
1734+ if ( this . #isBackgroundFetch( v ) ) {
1735+ // NB: this cannot occur if v.__staleWhileFetching is set,
1736+ // because in that case, it would take on the size of the
1737+ // existing entry that it temporarily replaces.
1738+ return this . backgroundFetchSize
1739+ }
17161740 if ( sizeCalculation ) {
17171741 if ( typeof sizeCalculation !== 'function' ) {
17181742 throw new TypeError ( 'sizeCalculation must be a function' )
@@ -2161,14 +2185,14 @@ export class LRUCache<K extends {}, V extends {}, FC = unknown> {
21612185 status,
21622186 } = setOptions
21632187
2188+ const isBF = this . #isBackgroundFetch( v )
21642189 if ( v === undefined ) {
21652190 if ( status ) status . set = 'deleted'
21662191 this . delete ( k )
21672192 return this
21682193 }
21692194 let { noUpdateTTL = this . noUpdateTTL } = setOptions
21702195
2171- const isBF = this . #isBackgroundFetch( v )
21722196 if ( status && ! isBF ) status . value = v
21732197
21742198 const size = this . #requireSize(
@@ -2598,6 +2622,10 @@ export class LRUCache<K extends {}, V extends {}, FC = unknown> {
25982622 this . #set( k , bf , { ...fetchOpts . options , status : undefined } )
25992623 index = this . #keyMap. get ( k )
26002624 } else {
2625+ // do not call #set, because we do not want to adjust its place
2626+ // in the lru queue, as it has not yet been "used". Also, we don't
2627+ // need to worry about evicting for size, because a background fetch
2628+ // over a stale value is treated as the same size as its stale value.
26012629 this . #valList[ index ] = bf
26022630 }
26032631 return bf
0 commit comments