@nocobase/plugin-workflow 2.1.0-beta.2 → 2.1.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -661
- package/README.md +79 -10
- package/dist/client/214.7e602cfe7a8251b8.js +10 -0
- package/dist/client/261.7722d7400942730e.js +10 -0
- package/dist/client/67.f904ef4520868b8a.js +10 -0
- package/dist/client/964.6251d37b35710747.js +10 -0
- package/dist/client/hooks/{useWorkflowFilterActionProps.d.ts → useResourceFilterActionProps.d.ts} +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/nodes/create.d.ts +10 -0
- package/dist/client/nodes/destroy.d.ts +10 -0
- package/dist/client/nodes/index.d.ts +3 -0
- package/dist/client/nodes/query.d.ts +18 -2
- package/dist/client/nodes/update.d.ts +10 -0
- package/dist/client/schemas/collection.d.ts +8 -2
- package/dist/client/schemas/executions.d.ts +41 -23
- package/dist/client/triggers/collection.d.ts +14 -1
- package/dist/client/triggers/index.d.ts +4 -0
- package/dist/client/triggers/schedule/constants.d.ts +4 -0
- package/dist/client/triggers/schedule/index.d.ts +15 -0
- package/dist/common/collections/executions.d.ts +22 -22
- package/dist/common/collections/executions.js +12 -0
- package/dist/common/collections/jobs.js +7 -0
- package/dist/common/collections/workflows.d.ts +22 -9
- package/dist/common/collections/workflows.js +9 -1
- package/dist/externalVersion.js +15 -13
- package/dist/locale/zh-CN.json +4 -1
- package/dist/node_modules/cron-parser/lib/parser.js +1 -1
- package/dist/node_modules/cron-parser/package.json +1 -1
- package/dist/node_modules/joi/dist/joi-browser.min.js +1 -0
- package/dist/node_modules/joi/lib/annotate.js +175 -0
- package/dist/node_modules/joi/lib/base.js +1069 -0
- package/dist/node_modules/joi/lib/cache.js +143 -0
- package/dist/node_modules/joi/lib/common.js +216 -0
- package/dist/node_modules/joi/lib/compile.js +283 -0
- package/dist/node_modules/joi/lib/errors.js +271 -0
- package/dist/node_modules/joi/lib/extend.js +312 -0
- package/dist/node_modules/joi/lib/index.d.ts +2365 -0
- package/dist/node_modules/joi/lib/index.js +1 -0
- package/dist/node_modules/joi/lib/manifest.js +476 -0
- package/dist/node_modules/joi/lib/messages.js +178 -0
- package/dist/node_modules/joi/lib/modify.js +267 -0
- package/dist/node_modules/joi/lib/ref.js +414 -0
- package/dist/node_modules/joi/lib/schemas.js +302 -0
- package/dist/node_modules/joi/lib/state.js +166 -0
- package/dist/node_modules/joi/lib/template.js +463 -0
- package/dist/node_modules/joi/lib/trace.js +346 -0
- package/dist/node_modules/joi/lib/types/alternatives.js +364 -0
- package/dist/node_modules/joi/lib/types/any.js +174 -0
- package/dist/node_modules/joi/lib/types/array.js +809 -0
- package/dist/node_modules/joi/lib/types/binary.js +100 -0
- package/dist/node_modules/joi/lib/types/boolean.js +150 -0
- package/dist/node_modules/joi/lib/types/date.js +233 -0
- package/dist/node_modules/joi/lib/types/function.js +93 -0
- package/dist/node_modules/joi/lib/types/keys.js +1067 -0
- package/dist/node_modules/joi/lib/types/link.js +168 -0
- package/dist/node_modules/joi/lib/types/number.js +363 -0
- package/dist/node_modules/joi/lib/types/object.js +22 -0
- package/dist/node_modules/joi/lib/types/string.js +850 -0
- package/dist/node_modules/joi/lib/types/symbol.js +102 -0
- package/dist/node_modules/joi/lib/validator.js +750 -0
- package/dist/node_modules/joi/lib/values.js +263 -0
- package/dist/node_modules/joi/node_modules/@hapi/topo/lib/index.d.ts +60 -0
- package/dist/node_modules/joi/node_modules/@hapi/topo/lib/index.js +225 -0
- package/dist/node_modules/joi/node_modules/@hapi/topo/package.json +30 -0
- package/dist/node_modules/joi/package.json +1 -0
- package/dist/node_modules/lru-cache/dist/commonjs/diagnostics-channel.d.ts +5 -0
- package/dist/node_modules/lru-cache/dist/commonjs/diagnostics-channel.js +10 -0
- package/dist/node_modules/lru-cache/dist/commonjs/index.d.ts +1381 -0
- package/dist/node_modules/lru-cache/dist/commonjs/index.js +1692 -0
- package/dist/node_modules/lru-cache/dist/commonjs/index.min.js +1 -0
- package/dist/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.d.ts +5 -0
- package/dist/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.js +4 -0
- package/dist/node_modules/lru-cache/dist/esm/browser/index.d.ts +1381 -0
- package/dist/node_modules/lru-cache/dist/{mjs → esm/browser}/index.js +537 -179
- package/dist/node_modules/lru-cache/dist/esm/browser/index.min.js +2 -0
- package/dist/node_modules/lru-cache/dist/esm/diagnostics-channel.d.ts +5 -0
- package/dist/node_modules/lru-cache/dist/esm/diagnostics-channel.js +19 -0
- package/dist/node_modules/lru-cache/dist/esm/index.d.ts +1381 -0
- package/dist/node_modules/lru-cache/dist/{cjs → esm}/index.js +538 -184
- package/dist/node_modules/lru-cache/dist/esm/index.min.js +2 -0
- package/dist/node_modules/lru-cache/dist/esm/node/diagnostics-channel.d.ts +5 -0
- package/dist/node_modules/lru-cache/dist/esm/node/diagnostics-channel.js +7 -0
- package/dist/node_modules/lru-cache/dist/esm/node/index.d.ts +1381 -0
- package/dist/node_modules/lru-cache/dist/esm/node/index.js +1688 -0
- package/dist/node_modules/lru-cache/dist/esm/node/index.min.js +2 -0
- package/dist/node_modules/lru-cache/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/nodejs_snowflake.js +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/server/Dispatcher.d.ts +3 -2
- package/dist/server/Dispatcher.js +74 -61
- package/dist/server/Plugin.d.ts +1 -0
- package/dist/server/Plugin.js +28 -3
- package/dist/server/actions/nodes.d.ts +5 -0
- package/dist/server/actions/nodes.js +38 -5
- package/dist/server/actions/workflows.d.ts +6 -0
- package/dist/server/actions/workflows.js +38 -0
- package/dist/server/instructions/ConditionInstruction.d.ts +2 -0
- package/dist/server/instructions/ConditionInstruction.js +17 -0
- package/dist/server/instructions/CreateInstruction.d.ts +3 -0
- package/dist/server/instructions/CreateInstruction.js +25 -0
- package/dist/server/instructions/DestroyInstruction.d.ts +3 -0
- package/dist/server/instructions/DestroyInstruction.js +25 -0
- package/dist/server/instructions/EndInstruction.d.ts +2 -0
- package/dist/server/instructions/EndInstruction.js +4 -0
- package/dist/server/instructions/MultiConditionsInstruction.d.ts +2 -0
- package/dist/server/instructions/MultiConditionsInstruction.js +23 -0
- package/dist/server/instructions/OutputInstruction.d.ts +2 -0
- package/dist/server/instructions/OutputInstruction.js +14 -0
- package/dist/server/instructions/QueryInstruction.d.ts +3 -0
- package/dist/server/instructions/QueryInstruction.js +32 -7
- package/dist/server/instructions/UpdateInstruction.d.ts +3 -0
- package/dist/server/instructions/UpdateInstruction.js +27 -0
- package/dist/server/instructions/index.d.ts +15 -2
- package/dist/server/instructions/index.js +18 -0
- package/dist/server/triggers/CollectionTrigger.d.ts +3 -0
- package/dist/server/triggers/CollectionTrigger.js +28 -0
- package/dist/server/triggers/ScheduleTrigger/index.d.ts +3 -0
- package/dist/server/triggers/ScheduleTrigger/index.js +18 -3
- package/dist/server/triggers/index.d.ts +3 -0
- package/dist/server/triggers/index.js +18 -0
- package/dist/server/utils.d.ts +17 -0
- package/dist/server/utils.js +51 -2
- package/dist/swagger/index.d.ts +830 -109
- package/dist/swagger/index.js +947 -208
- package/package.json +6 -5
- package/dist/client/27bd65abee87cafa.js +0 -10
- package/dist/client/478692c1637f2742.js +0 -10
- package/dist/client/c1347b9d21f864d9.js +0 -10
- package/dist/client/f39e94207f92e352.js +0 -10
- package/dist/node_modules/lru-cache/LICENSE +0 -15
- package/dist/node_modules/lru-cache/dist/cjs/index-cjs.d.ts +0 -7
- package/dist/node_modules/lru-cache/dist/cjs/index-cjs.js +0 -1
- package/dist/node_modules/lru-cache/dist/cjs/index.d.ts +0 -807
- package/dist/node_modules/lru-cache/dist/cjs/index.min.js +0 -2
- package/dist/node_modules/lru-cache/dist/mjs/index.d.ts +0 -807
- package/dist/node_modules/lru-cache/dist/mjs/index.min.js +0 -2
- /package/dist/node_modules/lru-cache/dist/{cjs → commonjs}/package.json +0 -0
- /package/dist/node_modules/lru-cache/dist/{mjs → esm}/package.json +0 -0
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module LRUCache
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
import { metrics, tracing } from './diagnostics-channel.js';
|
|
5
|
+
const hasSubscribers = () => metrics.hasSubscribers || tracing.hasSubscribers;
|
|
6
|
+
const defaultPerf = (typeof performance === 'object' &&
|
|
5
7
|
performance &&
|
|
6
|
-
typeof performance.now === 'function'
|
|
7
|
-
|
|
8
|
+
typeof performance.now === 'function') ?
|
|
9
|
+
performance
|
|
8
10
|
: Date;
|
|
9
11
|
const warned = new Set();
|
|
12
|
+
/* c8 ignore start */
|
|
13
|
+
const PROCESS = (typeof process === 'object' && !!process ?
|
|
14
|
+
process
|
|
15
|
+
: {});
|
|
16
|
+
/* c8 ignore stop */
|
|
10
17
|
const emitWarning = (msg, type, code, fn) => {
|
|
11
|
-
typeof
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
if (typeof PROCESS.emitWarning === 'function') {
|
|
19
|
+
PROCESS.emitWarning(msg, type, code, fn);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
//oxlint-disable-next-line no-console
|
|
23
|
+
console.error(`[${code}] ${type}: ${msg}`);
|
|
24
|
+
}
|
|
16
25
|
};
|
|
17
26
|
const shouldWarn = (code) => !warned.has(code);
|
|
18
27
|
const TYPE = Symbol('type');
|
|
19
|
-
const isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
|
|
20
|
-
/* c8 ignore start */
|
|
28
|
+
const isPosInt = (n) => !!n && n === Math.floor(n) && n > 0 && isFinite(n);
|
|
21
29
|
// This is a little bit ridiculous, tbh.
|
|
22
30
|
// The maximum array length is 2^32-1 or thereabouts on most JS impls.
|
|
23
31
|
// And well before that point, you're caching the entire world, I mean,
|
|
@@ -26,16 +34,12 @@ const isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
|
|
|
26
34
|
// zeroes at init time is brutal when you get that big.
|
|
27
35
|
// But why not be complete?
|
|
28
36
|
// Maybe in the future, these limits will have expanded.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
: max <= Math.pow(2, 8)
|
|
32
|
-
?
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
: max <= Math.pow(2, 32)
|
|
36
|
-
? Uint32Array
|
|
37
|
-
: max <= Number.MAX_SAFE_INTEGER
|
|
38
|
-
? ZeroArray
|
|
37
|
+
/* c8 ignore start */
|
|
38
|
+
const getUintArray = (max) => !isPosInt(max) ? null
|
|
39
|
+
: max <= Math.pow(2, 8) ? Uint8Array
|
|
40
|
+
: max <= Math.pow(2, 16) ? Uint16Array
|
|
41
|
+
: max <= Math.pow(2, 32) ? Uint32Array
|
|
42
|
+
: max <= Number.MAX_SAFE_INTEGER ? ZeroArray
|
|
39
43
|
: null;
|
|
40
44
|
/* c8 ignore stop */
|
|
41
45
|
class ZeroArray extends Array {
|
|
@@ -77,21 +81,34 @@ class Stack {
|
|
|
77
81
|
/**
|
|
78
82
|
* Default export, the thing you're using this module to get.
|
|
79
83
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
84
|
+
* The `K` and `V` types define the key and value types, respectively. The
|
|
85
|
+
* optional `FC` type defines the type of the `context` object passed to
|
|
86
|
+
* `cache.fetch()` and `cache.memo()`.
|
|
87
|
+
*
|
|
88
|
+
* Keys and values **must not** be `null` or `undefined`.
|
|
89
|
+
*
|
|
90
|
+
* All properties from the options object (with the exception of `max`,
|
|
91
|
+
* `maxSize`, `fetchMethod`, `memoMethod`, `dispose` and `disposeAfter`) are
|
|
92
|
+
* added as normal public members. (The listed options are read-only getters.)
|
|
93
|
+
*
|
|
94
|
+
* Changing any of these will alter the defaults for subsequent method calls.
|
|
85
95
|
*/
|
|
86
96
|
export class LRUCache {
|
|
87
|
-
//
|
|
88
|
-
// really *need* to be protected. The rest can be modified, as they just
|
|
89
|
-
// set defaults for various methods.
|
|
97
|
+
// options that cannot be changed without disaster
|
|
90
98
|
#max;
|
|
91
99
|
#maxSize;
|
|
92
100
|
#dispose;
|
|
101
|
+
#onInsert;
|
|
93
102
|
#disposeAfter;
|
|
94
103
|
#fetchMethod;
|
|
104
|
+
#memoMethod;
|
|
105
|
+
#perf;
|
|
106
|
+
/**
|
|
107
|
+
* {@link LRUCache.OptionsBase.perf}
|
|
108
|
+
*/
|
|
109
|
+
get perf() {
|
|
110
|
+
return this.#perf;
|
|
111
|
+
}
|
|
95
112
|
/**
|
|
96
113
|
* {@link LRUCache.OptionsBase.ttl}
|
|
97
114
|
*/
|
|
@@ -167,9 +184,11 @@ export class LRUCache {
|
|
|
167
184
|
#sizes;
|
|
168
185
|
#starts;
|
|
169
186
|
#ttls;
|
|
187
|
+
#autopurgeTimers;
|
|
170
188
|
#hasDispose;
|
|
171
189
|
#hasFetchMethod;
|
|
172
190
|
#hasDisposeAfter;
|
|
191
|
+
#hasOnInsert;
|
|
173
192
|
/**
|
|
174
193
|
* Do not call this method unless you need to inspect the
|
|
175
194
|
* inner workings of the cache. If anything returned by this
|
|
@@ -184,6 +203,7 @@ export class LRUCache {
|
|
|
184
203
|
// properties
|
|
185
204
|
starts: c.#starts,
|
|
186
205
|
ttls: c.#ttls,
|
|
206
|
+
autopurgeTimers: c.#autopurgeTimers,
|
|
187
207
|
sizes: c.#sizes,
|
|
188
208
|
keyMap: c.#keyMap,
|
|
189
209
|
keyList: c.#keyList,
|
|
@@ -237,12 +257,21 @@ export class LRUCache {
|
|
|
237
257
|
get fetchMethod() {
|
|
238
258
|
return this.#fetchMethod;
|
|
239
259
|
}
|
|
260
|
+
get memoMethod() {
|
|
261
|
+
return this.#memoMethod;
|
|
262
|
+
}
|
|
240
263
|
/**
|
|
241
264
|
* {@link LRUCache.OptionsBase.dispose} (read-only)
|
|
242
265
|
*/
|
|
243
266
|
get dispose() {
|
|
244
267
|
return this.#dispose;
|
|
245
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* {@link LRUCache.OptionsBase.onInsert} (read-only)
|
|
271
|
+
*/
|
|
272
|
+
get onInsert() {
|
|
273
|
+
return this.#onInsert;
|
|
274
|
+
}
|
|
246
275
|
/**
|
|
247
276
|
* {@link LRUCache.OptionsBase.disposeAfter} (read-only)
|
|
248
277
|
*/
|
|
@@ -250,7 +279,13 @@ export class LRUCache {
|
|
|
250
279
|
return this.#disposeAfter;
|
|
251
280
|
}
|
|
252
281
|
constructor(options) {
|
|
253
|
-
const { max = 0, ttl, ttlResolution = 1, ttlAutopurge, updateAgeOnGet, updateAgeOnHas, allowStale, dispose, disposeAfter, noDisposeOnSet, noUpdateTTL, maxSize = 0, maxEntrySize = 0, sizeCalculation, fetchMethod, noDeleteOnFetchRejection, noDeleteOnStaleGet, allowStaleOnFetchRejection, allowStaleOnFetchAbort, ignoreFetchAbort, } = options;
|
|
282
|
+
const { max = 0, ttl, ttlResolution = 1, ttlAutopurge, updateAgeOnGet, updateAgeOnHas, allowStale, dispose, onInsert, disposeAfter, noDisposeOnSet, noUpdateTTL, maxSize = 0, maxEntrySize = 0, sizeCalculation, fetchMethod, memoMethod, noDeleteOnFetchRejection, noDeleteOnStaleGet, allowStaleOnFetchRejection, allowStaleOnFetchAbort, ignoreFetchAbort, perf, } = options;
|
|
283
|
+
if (perf !== undefined) {
|
|
284
|
+
if (typeof perf?.now !== 'function') {
|
|
285
|
+
throw new TypeError('perf option must have a now() method if specified');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
this.#perf = perf ?? defaultPerf;
|
|
254
289
|
if (max !== 0 && !isPosInt(max)) {
|
|
255
290
|
throw new TypeError('max option must be a nonnegative integer');
|
|
256
291
|
}
|
|
@@ -270,15 +305,18 @@ export class LRUCache {
|
|
|
270
305
|
throw new TypeError('sizeCalculation set to non-function');
|
|
271
306
|
}
|
|
272
307
|
}
|
|
273
|
-
if (
|
|
274
|
-
|
|
308
|
+
if (memoMethod !== undefined && typeof memoMethod !== 'function') {
|
|
309
|
+
throw new TypeError('memoMethod must be a function if defined');
|
|
310
|
+
}
|
|
311
|
+
this.#memoMethod = memoMethod;
|
|
312
|
+
if (fetchMethod !== undefined && typeof fetchMethod !== 'function') {
|
|
275
313
|
throw new TypeError('fetchMethod must be a function if specified');
|
|
276
314
|
}
|
|
277
315
|
this.#fetchMethod = fetchMethod;
|
|
278
316
|
this.#hasFetchMethod = !!fetchMethod;
|
|
279
317
|
this.#keyMap = new Map();
|
|
280
|
-
this.#keyList =
|
|
281
|
-
this.#valList =
|
|
318
|
+
this.#keyList = Array.from({ length: max }).fill(undefined);
|
|
319
|
+
this.#valList = Array.from({ length: max }).fill(undefined);
|
|
282
320
|
this.#next = new UintArray(max);
|
|
283
321
|
this.#prev = new UintArray(max);
|
|
284
322
|
this.#head = 0;
|
|
@@ -289,6 +327,9 @@ export class LRUCache {
|
|
|
289
327
|
if (typeof dispose === 'function') {
|
|
290
328
|
this.#dispose = dispose;
|
|
291
329
|
}
|
|
330
|
+
if (typeof onInsert === 'function') {
|
|
331
|
+
this.#onInsert = onInsert;
|
|
332
|
+
}
|
|
292
333
|
if (typeof disposeAfter === 'function') {
|
|
293
334
|
this.#disposeAfter = disposeAfter;
|
|
294
335
|
this.#disposed = [];
|
|
@@ -298,6 +339,7 @@ export class LRUCache {
|
|
|
298
339
|
this.#disposed = undefined;
|
|
299
340
|
}
|
|
300
341
|
this.#hasDispose = !!this.#dispose;
|
|
342
|
+
this.#hasOnInsert = !!this.#onInsert;
|
|
301
343
|
this.#hasDisposeAfter = !!this.#disposeAfter;
|
|
302
344
|
this.noDisposeOnSet = !!noDisposeOnSet;
|
|
303
345
|
this.noUpdateTTL = !!noUpdateTTL;
|
|
@@ -322,9 +364,7 @@ export class LRUCache {
|
|
|
322
364
|
this.updateAgeOnGet = !!updateAgeOnGet;
|
|
323
365
|
this.updateAgeOnHas = !!updateAgeOnHas;
|
|
324
366
|
this.ttlResolution =
|
|
325
|
-
isPosInt(ttlResolution) || ttlResolution === 0
|
|
326
|
-
? ttlResolution
|
|
327
|
-
: 1;
|
|
367
|
+
isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1;
|
|
328
368
|
this.ttlAutopurge = !!ttlAutopurge;
|
|
329
369
|
this.ttl = ttl || 0;
|
|
330
370
|
if (this.ttl) {
|
|
@@ -348,7 +388,8 @@ export class LRUCache {
|
|
|
348
388
|
}
|
|
349
389
|
}
|
|
350
390
|
/**
|
|
351
|
-
* Return the
|
|
391
|
+
* Return the number of ms left in the item's TTL. If item is not in cache,
|
|
392
|
+
* returns `0`. Returns `Infinity` if item is in cache without a defined TTL.
|
|
352
393
|
*/
|
|
353
394
|
getRemainingTTL(key) {
|
|
354
395
|
return this.#keyMap.has(key) ? Infinity : 0;
|
|
@@ -358,41 +399,68 @@ export class LRUCache {
|
|
|
358
399
|
const starts = new ZeroArray(this.#max);
|
|
359
400
|
this.#ttls = ttls;
|
|
360
401
|
this.#starts = starts;
|
|
361
|
-
|
|
402
|
+
const purgeTimers = this.ttlAutopurge ?
|
|
403
|
+
Array.from({
|
|
404
|
+
length: this.#max,
|
|
405
|
+
})
|
|
406
|
+
: undefined;
|
|
407
|
+
this.#autopurgeTimers = purgeTimers;
|
|
408
|
+
this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
|
|
362
409
|
starts[index] = ttl !== 0 ? start : 0;
|
|
363
410
|
ttls[index] = ttl;
|
|
364
|
-
|
|
365
|
-
const t = setTimeout(() => {
|
|
366
|
-
if (this.#isStale(index)) {
|
|
367
|
-
this.delete(this.#keyList[index]);
|
|
368
|
-
}
|
|
369
|
-
}, ttl + 1);
|
|
370
|
-
// unref() not supported on all platforms
|
|
371
|
-
/* c8 ignore start */
|
|
372
|
-
if (t.unref) {
|
|
373
|
-
t.unref();
|
|
374
|
-
}
|
|
375
|
-
/* c8 ignore stop */
|
|
376
|
-
}
|
|
411
|
+
setPurgetTimer(index, ttl);
|
|
377
412
|
};
|
|
378
413
|
this.#updateItemAge = index => {
|
|
379
|
-
starts[index] = ttls[index] !== 0 ? perf.now() : 0;
|
|
414
|
+
starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0;
|
|
415
|
+
setPurgetTimer(index, ttls[index]);
|
|
380
416
|
};
|
|
417
|
+
// clear out the purge timer if we're setting TTL to 0, and
|
|
418
|
+
// previously had a ttl purge timer running, so it doesn't
|
|
419
|
+
// fire unnecessarily. Don't need to do this if we're not doing
|
|
420
|
+
// autopurge.
|
|
421
|
+
const setPurgetTimer = !this.ttlAutopurge ?
|
|
422
|
+
() => { }
|
|
423
|
+
: (index, ttl) => {
|
|
424
|
+
if (purgeTimers?.[index]) {
|
|
425
|
+
clearTimeout(purgeTimers[index]);
|
|
426
|
+
purgeTimers[index] = undefined;
|
|
427
|
+
}
|
|
428
|
+
if (ttl && ttl !== 0 && purgeTimers) {
|
|
429
|
+
const t = setTimeout(() => {
|
|
430
|
+
if (this.#isStale(index)) {
|
|
431
|
+
this.#delete(this.#keyList[index], 'expire');
|
|
432
|
+
}
|
|
433
|
+
}, ttl + 1);
|
|
434
|
+
// unref() not supported on all platforms
|
|
435
|
+
/* c8 ignore start */
|
|
436
|
+
if (t.unref) {
|
|
437
|
+
t.unref();
|
|
438
|
+
}
|
|
439
|
+
/* c8 ignore stop */
|
|
440
|
+
purgeTimers[index] = t;
|
|
441
|
+
}
|
|
442
|
+
};
|
|
381
443
|
this.#statusTTL = (status, index) => {
|
|
382
444
|
if (ttls[index]) {
|
|
383
445
|
const ttl = ttls[index];
|
|
384
446
|
const start = starts[index];
|
|
447
|
+
/* c8 ignore start */
|
|
448
|
+
if (!ttl || !start) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
/* c8 ignore stop */
|
|
385
452
|
status.ttl = ttl;
|
|
386
453
|
status.start = start;
|
|
387
454
|
status.now = cachedNow || getNow();
|
|
388
|
-
|
|
455
|
+
const age = status.now - start;
|
|
456
|
+
status.remainingTTL = ttl - age;
|
|
389
457
|
}
|
|
390
458
|
};
|
|
391
459
|
// debounce calls to perf.now() to 1s so we're not hitting
|
|
392
460
|
// that costly call repeatedly.
|
|
393
461
|
let cachedNow = 0;
|
|
394
462
|
const getNow = () => {
|
|
395
|
-
const n = perf.now();
|
|
463
|
+
const n = this.#perf.now();
|
|
396
464
|
if (this.ttlResolution > 0) {
|
|
397
465
|
cachedNow = n;
|
|
398
466
|
const t = setTimeout(() => (cachedNow = 0), this.ttlResolution);
|
|
@@ -410,14 +478,18 @@ export class LRUCache {
|
|
|
410
478
|
if (index === undefined) {
|
|
411
479
|
return 0;
|
|
412
480
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
481
|
+
const ttl = ttls[index];
|
|
482
|
+
const start = starts[index];
|
|
483
|
+
if (!ttl || !start) {
|
|
484
|
+
return Infinity;
|
|
485
|
+
}
|
|
486
|
+
const age = (cachedNow || getNow()) - start;
|
|
487
|
+
return ttl - age;
|
|
416
488
|
};
|
|
417
489
|
this.#isStale = index => {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
490
|
+
const s = starts[index];
|
|
491
|
+
const t = ttls[index];
|
|
492
|
+
return !!t && !!s && (cachedNow || getNow()) - s > t;
|
|
421
493
|
};
|
|
422
494
|
}
|
|
423
495
|
// conditionally set private methods related to TTL
|
|
@@ -483,10 +555,7 @@ export class LRUCache {
|
|
|
483
555
|
};
|
|
484
556
|
*#indexes({ allowStale = this.allowStale } = {}) {
|
|
485
557
|
if (this.#size) {
|
|
486
|
-
for (let i = this.#tail;
|
|
487
|
-
if (!this.#isValidIndex(i)) {
|
|
488
|
-
break;
|
|
489
|
-
}
|
|
558
|
+
for (let i = this.#tail; this.#isValidIndex(i);) {
|
|
490
559
|
if (allowStale || !this.#isStale(i)) {
|
|
491
560
|
yield i;
|
|
492
561
|
}
|
|
@@ -501,10 +570,7 @@ export class LRUCache {
|
|
|
501
570
|
}
|
|
502
571
|
*#rindexes({ allowStale = this.allowStale } = {}) {
|
|
503
572
|
if (this.#size) {
|
|
504
|
-
for (let i = this.#head;
|
|
505
|
-
if (!this.#isValidIndex(i)) {
|
|
506
|
-
break;
|
|
507
|
-
}
|
|
573
|
+
for (let i = this.#head; this.#isValidIndex(i);) {
|
|
508
574
|
if (allowStale || !this.#isStale(i)) {
|
|
509
575
|
yield i;
|
|
510
576
|
}
|
|
@@ -556,8 +622,7 @@ export class LRUCache {
|
|
|
556
622
|
*keys() {
|
|
557
623
|
for (const i of this.#indexes()) {
|
|
558
624
|
const k = this.#keyList[i];
|
|
559
|
-
if (k !== undefined &&
|
|
560
|
-
!this.#isBackgroundFetch(this.#valList[i])) {
|
|
625
|
+
if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
561
626
|
yield k;
|
|
562
627
|
}
|
|
563
628
|
}
|
|
@@ -571,8 +636,7 @@ export class LRUCache {
|
|
|
571
636
|
*rkeys() {
|
|
572
637
|
for (const i of this.#rindexes()) {
|
|
573
638
|
const k = this.#keyList[i];
|
|
574
|
-
if (k !== undefined &&
|
|
575
|
-
!this.#isBackgroundFetch(this.#valList[i])) {
|
|
639
|
+
if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
576
640
|
yield k;
|
|
577
641
|
}
|
|
578
642
|
}
|
|
@@ -584,8 +648,7 @@ export class LRUCache {
|
|
|
584
648
|
*values() {
|
|
585
649
|
for (const i of this.#indexes()) {
|
|
586
650
|
const v = this.#valList[i];
|
|
587
|
-
if (v !== undefined &&
|
|
588
|
-
!this.#isBackgroundFetch(this.#valList[i])) {
|
|
651
|
+
if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
589
652
|
yield this.#valList[i];
|
|
590
653
|
}
|
|
591
654
|
}
|
|
@@ -599,8 +662,7 @@ export class LRUCache {
|
|
|
599
662
|
*rvalues() {
|
|
600
663
|
for (const i of this.#rindexes()) {
|
|
601
664
|
const v = this.#valList[i];
|
|
602
|
-
if (v !== undefined &&
|
|
603
|
-
!this.#isBackgroundFetch(this.#valList[i])) {
|
|
665
|
+
if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
604
666
|
yield this.#valList[i];
|
|
605
667
|
}
|
|
606
668
|
}
|
|
@@ -612,35 +674,42 @@ export class LRUCache {
|
|
|
612
674
|
[Symbol.iterator]() {
|
|
613
675
|
return this.entries();
|
|
614
676
|
}
|
|
677
|
+
/**
|
|
678
|
+
* A String value that is used in the creation of the default string
|
|
679
|
+
* description of an object. Called by the built-in method
|
|
680
|
+
* `Object.prototype.toString`.
|
|
681
|
+
*/
|
|
682
|
+
[Symbol.toStringTag] = 'LRUCache';
|
|
615
683
|
/**
|
|
616
684
|
* Find a value for which the supplied fn method returns a truthy value,
|
|
617
|
-
* similar to Array.find()
|
|
685
|
+
* similar to `Array.find()`. fn is called as `fn(value, key, cache)`.
|
|
618
686
|
*/
|
|
619
687
|
find(fn, getOptions = {}) {
|
|
620
688
|
for (const i of this.#indexes()) {
|
|
621
689
|
const v = this.#valList[i];
|
|
622
|
-
const value = this.#isBackgroundFetch(v)
|
|
623
|
-
? v.__staleWhileFetching
|
|
624
|
-
: v;
|
|
690
|
+
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
625
691
|
if (value === undefined)
|
|
626
692
|
continue;
|
|
627
693
|
if (fn(value, this.#keyList[i], this)) {
|
|
628
|
-
return this
|
|
694
|
+
return this.#get(this.#keyList[i], getOptions);
|
|
629
695
|
}
|
|
630
696
|
}
|
|
631
697
|
}
|
|
632
698
|
/**
|
|
633
|
-
* Call the supplied function on each item in the cache, in order from
|
|
634
|
-
*
|
|
635
|
-
*
|
|
636
|
-
*
|
|
699
|
+
* Call the supplied function on each item in the cache, in order from most
|
|
700
|
+
* recently used to least recently used.
|
|
701
|
+
*
|
|
702
|
+
* `fn` is called as `fn(value, key, cache)`.
|
|
703
|
+
*
|
|
704
|
+
* If `thisp` is provided, function will be called in the `this`-context of
|
|
705
|
+
* the provided object, or the cache if no `thisp` object is provided.
|
|
706
|
+
*
|
|
707
|
+
* Does not update age or recenty of use, or iterate over stale values.
|
|
637
708
|
*/
|
|
638
709
|
forEach(fn, thisp = this) {
|
|
639
710
|
for (const i of this.#indexes()) {
|
|
640
711
|
const v = this.#valList[i];
|
|
641
|
-
const value = this.#isBackgroundFetch(v)
|
|
642
|
-
? v.__staleWhileFetching
|
|
643
|
-
: v;
|
|
712
|
+
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
644
713
|
if (value === undefined)
|
|
645
714
|
continue;
|
|
646
715
|
fn.call(thisp, value, this.#keyList[i], this);
|
|
@@ -653,9 +722,7 @@ export class LRUCache {
|
|
|
653
722
|
rforEach(fn, thisp = this) {
|
|
654
723
|
for (const i of this.#rindexes()) {
|
|
655
724
|
const v = this.#valList[i];
|
|
656
|
-
const value = this.#isBackgroundFetch(v)
|
|
657
|
-
? v.__staleWhileFetching
|
|
658
|
-
: v;
|
|
725
|
+
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
659
726
|
if (value === undefined)
|
|
660
727
|
continue;
|
|
661
728
|
fn.call(thisp, value, this.#keyList[i], this);
|
|
@@ -669,24 +736,69 @@ export class LRUCache {
|
|
|
669
736
|
let deleted = false;
|
|
670
737
|
for (const i of this.#rindexes({ allowStale: true })) {
|
|
671
738
|
if (this.#isStale(i)) {
|
|
672
|
-
this
|
|
739
|
+
this.#delete(this.#keyList[i], 'expire');
|
|
673
740
|
deleted = true;
|
|
674
741
|
}
|
|
675
742
|
}
|
|
676
743
|
return deleted;
|
|
677
744
|
}
|
|
745
|
+
/**
|
|
746
|
+
* Get the extended info about a given entry, to get its value, size, and
|
|
747
|
+
* TTL info simultaneously. Returns `undefined` if the key is not present.
|
|
748
|
+
*
|
|
749
|
+
* Unlike {@link LRUCache#dump}, which is designed to be portable and survive
|
|
750
|
+
* serialization, the `start` value is always the current timestamp, and the
|
|
751
|
+
* `ttl` is a calculated remaining time to live (negative if expired).
|
|
752
|
+
*
|
|
753
|
+
* Always returns stale values, if their info is found in the cache, so be
|
|
754
|
+
* sure to check for expirations (ie, a negative {@link LRUCache.Entry#ttl})
|
|
755
|
+
* if relevant.
|
|
756
|
+
*/
|
|
757
|
+
info(key) {
|
|
758
|
+
const i = this.#keyMap.get(key);
|
|
759
|
+
if (i === undefined)
|
|
760
|
+
return undefined;
|
|
761
|
+
const v = this.#valList[i];
|
|
762
|
+
/* c8 ignore start - this isn't tested for the info function,
|
|
763
|
+
* but it's the same logic as found in other places. */
|
|
764
|
+
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
765
|
+
if (value === undefined)
|
|
766
|
+
return undefined;
|
|
767
|
+
/* c8 ignore stop */
|
|
768
|
+
const entry = { value };
|
|
769
|
+
if (this.#ttls && this.#starts) {
|
|
770
|
+
const ttl = this.#ttls[i];
|
|
771
|
+
const start = this.#starts[i];
|
|
772
|
+
if (ttl && start) {
|
|
773
|
+
const remain = ttl - (this.#perf.now() - start);
|
|
774
|
+
entry.ttl = remain;
|
|
775
|
+
entry.start = Date.now();
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
if (this.#sizes) {
|
|
779
|
+
entry.size = this.#sizes[i];
|
|
780
|
+
}
|
|
781
|
+
return entry;
|
|
782
|
+
}
|
|
678
783
|
/**
|
|
679
784
|
* Return an array of [key, {@link LRUCache.Entry}] tuples which can be
|
|
680
|
-
* passed to
|
|
785
|
+
* passed to {@link LRUCache#load}.
|
|
786
|
+
*
|
|
787
|
+
* The `start` fields are calculated relative to a portable `Date.now()`
|
|
788
|
+
* timestamp, even if `performance.now()` is available.
|
|
789
|
+
*
|
|
790
|
+
* Stale entries are always included in the `dump`, even if
|
|
791
|
+
* {@link LRUCache.OptionsBase.allowStale} is false.
|
|
792
|
+
*
|
|
793
|
+
* Note: this returns an actual array, not a generator, so it can be more
|
|
794
|
+
* easily passed around.
|
|
681
795
|
*/
|
|
682
796
|
dump() {
|
|
683
797
|
const arr = [];
|
|
684
798
|
for (const i of this.#indexes({ allowStale: true })) {
|
|
685
799
|
const key = this.#keyList[i];
|
|
686
800
|
const v = this.#valList[i];
|
|
687
|
-
const value = this.#isBackgroundFetch(v)
|
|
688
|
-
? v.__staleWhileFetching
|
|
689
|
-
: v;
|
|
801
|
+
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
690
802
|
if (value === undefined || key === undefined)
|
|
691
803
|
continue;
|
|
692
804
|
const entry = { value };
|
|
@@ -694,7 +806,7 @@ export class LRUCache {
|
|
|
694
806
|
entry.ttl = this.#ttls[i];
|
|
695
807
|
// always dump the start relative to a portable timestamp
|
|
696
808
|
// it's ok for this to be a bit slow, it's a rare operation.
|
|
697
|
-
const age = perf.now() - this.#starts[i];
|
|
809
|
+
const age = this.#perf.now() - this.#starts[i];
|
|
698
810
|
entry.start = Math.floor(Date.now() - age);
|
|
699
811
|
}
|
|
700
812
|
if (this.#sizes) {
|
|
@@ -706,8 +818,12 @@ export class LRUCache {
|
|
|
706
818
|
}
|
|
707
819
|
/**
|
|
708
820
|
* Reset the cache and load in the items in entries in the order listed.
|
|
709
|
-
*
|
|
710
|
-
*
|
|
821
|
+
*
|
|
822
|
+
* The shape of the resulting cache may be different if the same options are
|
|
823
|
+
* not used in both caches.
|
|
824
|
+
*
|
|
825
|
+
* The `start` fields are assumed to be calculated relative to a portable
|
|
826
|
+
* `Date.now()` timestamp, even if `performance.now()` is available.
|
|
711
827
|
*/
|
|
712
828
|
load(arr) {
|
|
713
829
|
this.clear();
|
|
@@ -720,38 +836,85 @@ export class LRUCache {
|
|
|
720
836
|
//
|
|
721
837
|
// it's ok for this to be a bit slow, it's a rare operation.
|
|
722
838
|
const age = Date.now() - entry.start;
|
|
723
|
-
entry.start = perf.now() - age;
|
|
839
|
+
entry.start = this.#perf.now() - age;
|
|
724
840
|
}
|
|
725
|
-
this
|
|
841
|
+
this.#set(key, entry.value, entry);
|
|
726
842
|
}
|
|
727
843
|
}
|
|
728
844
|
/**
|
|
729
845
|
* Add a value to the cache.
|
|
846
|
+
*
|
|
847
|
+
* Note: if `undefined` is specified as a value, this is an alias for
|
|
848
|
+
* {@link LRUCache#delete}
|
|
849
|
+
*
|
|
850
|
+
* Fields on the {@link LRUCache.SetOptions} options param will override
|
|
851
|
+
* their corresponding values in the constructor options for the scope
|
|
852
|
+
* of this single `set()` operation.
|
|
853
|
+
*
|
|
854
|
+
* If `start` is provided, then that will set the effective start
|
|
855
|
+
* time for the TTL calculation. Note that this must be a previous
|
|
856
|
+
* value of `performance.now()` if supported, or a previous value of
|
|
857
|
+
* `Date.now()` if not.
|
|
858
|
+
*
|
|
859
|
+
* Options object may also include `size`, which will prevent
|
|
860
|
+
* calling the `sizeCalculation` function and just use the specified
|
|
861
|
+
* number if it is a positive integer, and `noDisposeOnSet` which
|
|
862
|
+
* will prevent calling a `dispose` function in the case of
|
|
863
|
+
* overwrites.
|
|
864
|
+
*
|
|
865
|
+
* If the `size` (or return value of `sizeCalculation`) for a given
|
|
866
|
+
* entry is greater than `maxEntrySize`, then the item will not be
|
|
867
|
+
* added to the cache.
|
|
868
|
+
*
|
|
869
|
+
* Will update the recency of the entry.
|
|
870
|
+
*
|
|
871
|
+
* If the value is `undefined`, then this is an alias for
|
|
872
|
+
* `cache.delete(key)`. `undefined` is never stored in the cache.
|
|
730
873
|
*/
|
|
731
874
|
set(k, v, setOptions = {}) {
|
|
875
|
+
const { status = metrics.hasSubscribers ? {} : undefined } = setOptions;
|
|
876
|
+
setOptions.status = status;
|
|
877
|
+
if (status) {
|
|
878
|
+
status.op = 'set';
|
|
879
|
+
status.key = k;
|
|
880
|
+
if (v !== undefined)
|
|
881
|
+
status.value = v;
|
|
882
|
+
}
|
|
883
|
+
const result = this.#set(k, v, setOptions);
|
|
884
|
+
if (status && metrics.hasSubscribers) {
|
|
885
|
+
metrics.publish(status);
|
|
886
|
+
}
|
|
887
|
+
return result;
|
|
888
|
+
}
|
|
889
|
+
#set(k, v, setOptions = {}) {
|
|
732
890
|
const { ttl = this.ttl, start, noDisposeOnSet = this.noDisposeOnSet, sizeCalculation = this.sizeCalculation, status, } = setOptions;
|
|
891
|
+
if (v === undefined) {
|
|
892
|
+
if (status)
|
|
893
|
+
status.set = 'deleted';
|
|
894
|
+
this.delete(k);
|
|
895
|
+
return this;
|
|
896
|
+
}
|
|
733
897
|
let { noUpdateTTL = this.noUpdateTTL } = setOptions;
|
|
734
|
-
|
|
898
|
+
if (status && !this.#isBackgroundFetch(v))
|
|
899
|
+
status.value = v;
|
|
900
|
+
const size = this.#requireSize(k, v, setOptions.size || 0, sizeCalculation, status);
|
|
735
901
|
// if the item doesn't fit, don't do anything
|
|
736
902
|
// NB: maxEntrySize set to maxSize by default
|
|
737
903
|
if (this.maxEntrySize && size > this.maxEntrySize) {
|
|
904
|
+
// have to delete, in case something is there already.
|
|
905
|
+
this.#delete(k, 'set');
|
|
738
906
|
if (status) {
|
|
739
907
|
status.set = 'miss';
|
|
740
908
|
status.maxEntrySizeExceeded = true;
|
|
741
909
|
}
|
|
742
|
-
// have to delete, in case something is there already.
|
|
743
|
-
this.delete(k);
|
|
744
910
|
return this;
|
|
745
911
|
}
|
|
746
912
|
let index = this.#size === 0 ? undefined : this.#keyMap.get(k);
|
|
747
913
|
if (index === undefined) {
|
|
748
914
|
// addition
|
|
749
|
-
index = (this.#size === 0
|
|
750
|
-
? this.#
|
|
751
|
-
|
|
752
|
-
? this.#free.pop()
|
|
753
|
-
: this.#size === this.#max
|
|
754
|
-
? this.#evict(false)
|
|
915
|
+
index = (this.#size === 0 ? this.#tail
|
|
916
|
+
: this.#free.length !== 0 ? this.#free.pop()
|
|
917
|
+
: this.#size === this.#max ? this.#evict(false)
|
|
755
918
|
: this.#size);
|
|
756
919
|
this.#keyList[index] = k;
|
|
757
920
|
this.#valList[index] = v;
|
|
@@ -764,6 +927,9 @@ export class LRUCache {
|
|
|
764
927
|
if (status)
|
|
765
928
|
status.set = 'add';
|
|
766
929
|
noUpdateTTL = false;
|
|
930
|
+
if (this.#hasOnInsert) {
|
|
931
|
+
this.#onInsert?.(v, k, 'add');
|
|
932
|
+
}
|
|
767
933
|
}
|
|
768
934
|
else {
|
|
769
935
|
// update
|
|
@@ -772,6 +938,15 @@ export class LRUCache {
|
|
|
772
938
|
if (v !== oldVal) {
|
|
773
939
|
if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {
|
|
774
940
|
oldVal.__abortController.abort(new Error('replaced'));
|
|
941
|
+
const { __staleWhileFetching: s } = oldVal;
|
|
942
|
+
if (s !== undefined && !noDisposeOnSet) {
|
|
943
|
+
if (this.#hasDispose) {
|
|
944
|
+
this.#dispose?.(s, k, 'set');
|
|
945
|
+
}
|
|
946
|
+
if (this.#hasDisposeAfter) {
|
|
947
|
+
this.#disposed?.push([s, k, 'set']);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
775
950
|
}
|
|
776
951
|
else if (!noDisposeOnSet) {
|
|
777
952
|
if (this.#hasDispose) {
|
|
@@ -786,8 +961,8 @@ export class LRUCache {
|
|
|
786
961
|
this.#valList[index] = v;
|
|
787
962
|
if (status) {
|
|
788
963
|
status.set = 'replace';
|
|
789
|
-
const oldValue = oldVal && this.#isBackgroundFetch(oldVal)
|
|
790
|
-
|
|
964
|
+
const oldValue = oldVal && this.#isBackgroundFetch(oldVal) ?
|
|
965
|
+
oldVal.__staleWhileFetching
|
|
791
966
|
: oldVal;
|
|
792
967
|
if (oldValue !== undefined)
|
|
793
968
|
status.oldValue = oldValue;
|
|
@@ -796,6 +971,9 @@ export class LRUCache {
|
|
|
796
971
|
else if (status) {
|
|
797
972
|
status.set = 'update';
|
|
798
973
|
}
|
|
974
|
+
if (this.#hasOnInsert) {
|
|
975
|
+
this.onInsert?.(v, k, v === oldVal ? 'update' : 'replace');
|
|
976
|
+
}
|
|
799
977
|
}
|
|
800
978
|
if (ttl !== 0 && !this.#ttls) {
|
|
801
979
|
this.#initializeTTLTracking();
|
|
@@ -861,6 +1039,10 @@ export class LRUCache {
|
|
|
861
1039
|
}
|
|
862
1040
|
}
|
|
863
1041
|
this.#removeItemSize(head);
|
|
1042
|
+
if (this.#autopurgeTimers?.[head]) {
|
|
1043
|
+
clearTimeout(this.#autopurgeTimers[head]);
|
|
1044
|
+
this.#autopurgeTimers[head] = undefined;
|
|
1045
|
+
}
|
|
864
1046
|
// if we aren't about to use the index, then null these out
|
|
865
1047
|
if (free) {
|
|
866
1048
|
this.#keyList[head] = undefined;
|
|
@@ -883,10 +1065,30 @@ export class LRUCache {
|
|
|
883
1065
|
* Will return false if the item is stale, even though it is technically
|
|
884
1066
|
* in the cache.
|
|
885
1067
|
*
|
|
1068
|
+
* Check if a key is in the cache, without updating the recency of
|
|
1069
|
+
* use. Age is updated if {@link LRUCache.OptionsBase.updateAgeOnHas} is set
|
|
1070
|
+
* to `true` in either the options or the constructor.
|
|
1071
|
+
*
|
|
1072
|
+
* Will return `false` if the item is stale, even though it is technically in
|
|
1073
|
+
* the cache. The difference can be determined (if it matters) by using a
|
|
1074
|
+
* `status` argument, and inspecting the `has` field.
|
|
1075
|
+
*
|
|
886
1076
|
* Will not update item age unless
|
|
887
1077
|
* {@link LRUCache.OptionsBase.updateAgeOnHas} is set.
|
|
888
1078
|
*/
|
|
889
1079
|
has(k, hasOptions = {}) {
|
|
1080
|
+
const { status = metrics.hasSubscribers ? {} : undefined } = hasOptions;
|
|
1081
|
+
hasOptions.status = status;
|
|
1082
|
+
if (status) {
|
|
1083
|
+
status.op = 'has';
|
|
1084
|
+
status.key = k;
|
|
1085
|
+
}
|
|
1086
|
+
const result = this.#has(k, hasOptions);
|
|
1087
|
+
if (metrics.hasSubscribers)
|
|
1088
|
+
metrics.publish(status);
|
|
1089
|
+
return result;
|
|
1090
|
+
}
|
|
1091
|
+
#has(k, hasOptions = {}) {
|
|
890
1092
|
const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions;
|
|
891
1093
|
const index = this.#keyMap.get(k);
|
|
892
1094
|
if (index !== undefined) {
|
|
@@ -923,14 +1125,38 @@ export class LRUCache {
|
|
|
923
1125
|
* {@link LRUCache.OptionsBase.allowStale} is set.
|
|
924
1126
|
*/
|
|
925
1127
|
peek(k, peekOptions = {}) {
|
|
926
|
-
const {
|
|
1128
|
+
const { status = hasSubscribers() ? {} : undefined } = peekOptions;
|
|
1129
|
+
if (status) {
|
|
1130
|
+
status.op = 'peek';
|
|
1131
|
+
status.key = k;
|
|
1132
|
+
}
|
|
1133
|
+
peekOptions.status = status;
|
|
1134
|
+
const result = this.#peek(k, peekOptions);
|
|
1135
|
+
if (metrics.hasSubscribers) {
|
|
1136
|
+
metrics.publish(status);
|
|
1137
|
+
}
|
|
1138
|
+
return result;
|
|
1139
|
+
}
|
|
1140
|
+
#peek(k, peekOptions) {
|
|
1141
|
+
const { status, allowStale = this.allowStale } = peekOptions;
|
|
927
1142
|
const index = this.#keyMap.get(k);
|
|
928
|
-
if (index
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1143
|
+
if (index === undefined || (!allowStale && this.#isStale(index))) {
|
|
1144
|
+
if (status)
|
|
1145
|
+
status.peek = index === undefined ? 'miss' : 'stale';
|
|
1146
|
+
return undefined;
|
|
1147
|
+
}
|
|
1148
|
+
const v = this.#valList[index];
|
|
1149
|
+
const val = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
1150
|
+
if (status) {
|
|
1151
|
+
if (val !== undefined) {
|
|
1152
|
+
status.peek = 'hit';
|
|
1153
|
+
status.value = val;
|
|
1154
|
+
}
|
|
1155
|
+
else {
|
|
1156
|
+
status.peek = 'miss';
|
|
1157
|
+
}
|
|
933
1158
|
}
|
|
1159
|
+
return val;
|
|
934
1160
|
}
|
|
935
1161
|
#backgroundFetch(k, index, options, context) {
|
|
936
1162
|
const v = index === undefined ? undefined : this.#valList[index];
|
|
@@ -951,6 +1177,8 @@ export class LRUCache {
|
|
|
951
1177
|
const cb = (v, updateCache = false) => {
|
|
952
1178
|
const { aborted } = ac.signal;
|
|
953
1179
|
const ignoreAbort = options.ignoreFetchAbort && v !== undefined;
|
|
1180
|
+
const proceed = options.ignoreFetchAbort ||
|
|
1181
|
+
!!(options.allowStaleOnFetchAbort && v !== undefined);
|
|
954
1182
|
if (options.status) {
|
|
955
1183
|
if (aborted && !updateCache) {
|
|
956
1184
|
options.status.fetchAborted = true;
|
|
@@ -963,23 +1191,27 @@ export class LRUCache {
|
|
|
963
1191
|
}
|
|
964
1192
|
}
|
|
965
1193
|
if (aborted && !ignoreAbort && !updateCache) {
|
|
966
|
-
return fetchFail(ac.signal.reason);
|
|
1194
|
+
return fetchFail(ac.signal.reason, proceed);
|
|
967
1195
|
}
|
|
968
1196
|
// either we didn't abort, and are still here, or we did, and ignored
|
|
969
1197
|
const bf = p;
|
|
970
|
-
if
|
|
1198
|
+
// if nothing else has been written there but we're set to update the
|
|
1199
|
+
// cache and ignore the abort, or if it's still pending on this specific
|
|
1200
|
+
// background request, then write it to the cache.
|
|
1201
|
+
const vl = this.#valList[index];
|
|
1202
|
+
if (vl === p || (vl === undefined && ignoreAbort && updateCache)) {
|
|
971
1203
|
if (v === undefined) {
|
|
972
|
-
if (bf.__staleWhileFetching) {
|
|
1204
|
+
if (bf.__staleWhileFetching !== undefined) {
|
|
973
1205
|
this.#valList[index] = bf.__staleWhileFetching;
|
|
974
1206
|
}
|
|
975
1207
|
else {
|
|
976
|
-
this
|
|
1208
|
+
this.#delete(k, 'fetch');
|
|
977
1209
|
}
|
|
978
1210
|
}
|
|
979
1211
|
else {
|
|
980
1212
|
if (options.status)
|
|
981
1213
|
options.status.fetchUpdated = true;
|
|
982
|
-
this
|
|
1214
|
+
this.#set(k, v, fetchOpts.options);
|
|
983
1215
|
}
|
|
984
1216
|
}
|
|
985
1217
|
return v;
|
|
@@ -989,9 +1221,10 @@ export class LRUCache {
|
|
|
989
1221
|
options.status.fetchRejected = true;
|
|
990
1222
|
options.status.fetchError = er;
|
|
991
1223
|
}
|
|
992
|
-
|
|
1224
|
+
// do not pass go, do not collect $200
|
|
1225
|
+
return fetchFail(er, false);
|
|
993
1226
|
};
|
|
994
|
-
const fetchFail = (er) => {
|
|
1227
|
+
const fetchFail = (er, proceed) => {
|
|
995
1228
|
const { aborted } = ac.signal;
|
|
996
1229
|
const allowStaleAborted = aborted && options.allowStaleOnFetchAbort;
|
|
997
1230
|
const allowStale = allowStaleAborted || options.allowStaleOnFetchRejection;
|
|
@@ -1000,9 +1233,9 @@ export class LRUCache {
|
|
|
1000
1233
|
if (this.#valList[index] === p) {
|
|
1001
1234
|
// if we allow stale on fetch rejections, then we need to ensure that
|
|
1002
1235
|
// the stale value is not removed from the cache when the fetch fails.
|
|
1003
|
-
const del = !noDelete || bf.__staleWhileFetching === undefined;
|
|
1236
|
+
const del = !noDelete || (!proceed && bf.__staleWhileFetching === undefined);
|
|
1004
1237
|
if (del) {
|
|
1005
|
-
this
|
|
1238
|
+
this.#delete(k, 'fetch');
|
|
1006
1239
|
}
|
|
1007
1240
|
else if (!allowStaleAborted) {
|
|
1008
1241
|
// still replace the *promise* with the stale value,
|
|
@@ -1025,15 +1258,14 @@ export class LRUCache {
|
|
|
1025
1258
|
const pcall = (res, rej) => {
|
|
1026
1259
|
const fmp = this.#fetchMethod?.(k, v, fetchOpts);
|
|
1027
1260
|
if (fmp && fmp instanceof Promise) {
|
|
1028
|
-
fmp.then(v => res(v), rej);
|
|
1261
|
+
fmp.then(v => res(v === undefined ? undefined : v), rej);
|
|
1029
1262
|
}
|
|
1030
1263
|
// ignored, we go until we finish, regardless.
|
|
1031
1264
|
// defer check until we are actually aborting,
|
|
1032
1265
|
// so fetchMethod can override.
|
|
1033
1266
|
ac.signal.addEventListener('abort', () => {
|
|
1034
|
-
if (!options.ignoreFetchAbort ||
|
|
1035
|
-
|
|
1036
|
-
res();
|
|
1267
|
+
if (!options.ignoreFetchAbort || options.allowStaleOnFetchAbort) {
|
|
1268
|
+
res(undefined);
|
|
1037
1269
|
// when it eventually resolves, update the cache.
|
|
1038
1270
|
if (options.allowStaleOnFetchAbort) {
|
|
1039
1271
|
res = v => cb(v, true);
|
|
@@ -1051,7 +1283,7 @@ export class LRUCache {
|
|
|
1051
1283
|
});
|
|
1052
1284
|
if (index === undefined) {
|
|
1053
1285
|
// internal, don't expose status.
|
|
1054
|
-
this
|
|
1286
|
+
this.#set(k, bf, { ...fetchOpts.options, status: undefined });
|
|
1055
1287
|
index = this.#keyMap.get(k);
|
|
1056
1288
|
}
|
|
1057
1289
|
else {
|
|
@@ -1068,7 +1300,23 @@ export class LRUCache {
|
|
|
1068
1300
|
b.hasOwnProperty('__staleWhileFetching') &&
|
|
1069
1301
|
b.__abortController instanceof AbortController);
|
|
1070
1302
|
}
|
|
1071
|
-
|
|
1303
|
+
fetch(k, fetchOptions = {}) {
|
|
1304
|
+
const ths = tracing.hasSubscribers;
|
|
1305
|
+
const { status = hasSubscribers() ? {} : undefined } = fetchOptions;
|
|
1306
|
+
fetchOptions.status = status;
|
|
1307
|
+
if (status && fetchOptions.context) {
|
|
1308
|
+
status.context = fetchOptions.context;
|
|
1309
|
+
}
|
|
1310
|
+
const p = this.#fetch(k, fetchOptions);
|
|
1311
|
+
if (status && hasSubscribers()) {
|
|
1312
|
+
if (ths) {
|
|
1313
|
+
status.trace = true;
|
|
1314
|
+
tracing.tracePromise(() => p, status).catch(() => { });
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
return p;
|
|
1318
|
+
}
|
|
1319
|
+
async #fetch(k, fetchOptions = {}) {
|
|
1072
1320
|
const {
|
|
1073
1321
|
// get options
|
|
1074
1322
|
allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet,
|
|
@@ -1076,10 +1324,16 @@ export class LRUCache {
|
|
|
1076
1324
|
ttl = this.ttl, noDisposeOnSet = this.noDisposeOnSet, size = 0, sizeCalculation = this.sizeCalculation, noUpdateTTL = this.noUpdateTTL,
|
|
1077
1325
|
// fetch exclusive options
|
|
1078
1326
|
noDeleteOnFetchRejection = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection = this.allowStaleOnFetchRejection, ignoreFetchAbort = this.ignoreFetchAbort, allowStaleOnFetchAbort = this.allowStaleOnFetchAbort, context, forceRefresh = false, status, signal, } = fetchOptions;
|
|
1327
|
+
if (status) {
|
|
1328
|
+
status.op = 'fetch';
|
|
1329
|
+
status.key = k;
|
|
1330
|
+
if (forceRefresh)
|
|
1331
|
+
status.forceRefresh = true;
|
|
1332
|
+
}
|
|
1079
1333
|
if (!this.#hasFetchMethod) {
|
|
1080
1334
|
if (status)
|
|
1081
1335
|
status.fetch = 'get';
|
|
1082
|
-
return this
|
|
1336
|
+
return this.#get(k, {
|
|
1083
1337
|
allowStale,
|
|
1084
1338
|
updateAgeOnGet,
|
|
1085
1339
|
noDeleteOnStaleGet,
|
|
@@ -1148,6 +1402,71 @@ export class LRUCache {
|
|
|
1148
1402
|
return staleVal ? p.__staleWhileFetching : (p.__returned = p);
|
|
1149
1403
|
}
|
|
1150
1404
|
}
|
|
1405
|
+
forceFetch(k, fetchOptions = {}) {
|
|
1406
|
+
const ths = tracing.hasSubscribers;
|
|
1407
|
+
const { status = hasSubscribers() ? {} : undefined } = fetchOptions;
|
|
1408
|
+
fetchOptions.status = status;
|
|
1409
|
+
if (status && fetchOptions.context) {
|
|
1410
|
+
status.context = fetchOptions.context;
|
|
1411
|
+
}
|
|
1412
|
+
const p = this.#forceFetch(k, fetchOptions);
|
|
1413
|
+
if (status && hasSubscribers()) {
|
|
1414
|
+
if (ths) {
|
|
1415
|
+
status.trace = true;
|
|
1416
|
+
tracing.tracePromise(() => p, status).catch(() => { });
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
return p;
|
|
1420
|
+
}
|
|
1421
|
+
async #forceFetch(k, fetchOptions = {}) {
|
|
1422
|
+
const v = await this.#fetch(k, fetchOptions);
|
|
1423
|
+
if (v === undefined)
|
|
1424
|
+
throw new Error('fetch() returned undefined');
|
|
1425
|
+
return v;
|
|
1426
|
+
}
|
|
1427
|
+
memo(k, memoOptions = {}) {
|
|
1428
|
+
const { status = metrics.hasSubscribers ? {} : undefined } = memoOptions;
|
|
1429
|
+
memoOptions.status = status;
|
|
1430
|
+
if (status) {
|
|
1431
|
+
status.op = 'memo';
|
|
1432
|
+
status.key = k;
|
|
1433
|
+
if (memoOptions.context) {
|
|
1434
|
+
status.context = memoOptions.context;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
const result = this.#memo(k, memoOptions);
|
|
1438
|
+
if (status)
|
|
1439
|
+
status.value = result;
|
|
1440
|
+
if (metrics.hasSubscribers)
|
|
1441
|
+
metrics.publish(status);
|
|
1442
|
+
return result;
|
|
1443
|
+
}
|
|
1444
|
+
#memo(k, memoOptions = {}) {
|
|
1445
|
+
const memoMethod = this.#memoMethod;
|
|
1446
|
+
if (!memoMethod) {
|
|
1447
|
+
throw new Error('no memoMethod provided to constructor');
|
|
1448
|
+
}
|
|
1449
|
+
const { context, status, forceRefresh, ...options } = memoOptions;
|
|
1450
|
+
if (status && forceRefresh)
|
|
1451
|
+
status.forceRefresh = true;
|
|
1452
|
+
const v = this.#get(k, options);
|
|
1453
|
+
const refresh = forceRefresh || v === undefined;
|
|
1454
|
+
if (status) {
|
|
1455
|
+
status.memo = refresh ? 'miss' : 'hit';
|
|
1456
|
+
if (!refresh)
|
|
1457
|
+
status.value = v;
|
|
1458
|
+
}
|
|
1459
|
+
if (!refresh)
|
|
1460
|
+
return v;
|
|
1461
|
+
const vv = memoMethod(k, v, {
|
|
1462
|
+
options,
|
|
1463
|
+
context,
|
|
1464
|
+
});
|
|
1465
|
+
if (status)
|
|
1466
|
+
status.value = vv;
|
|
1467
|
+
this.#set(k, vv, options);
|
|
1468
|
+
return vv;
|
|
1469
|
+
}
|
|
1151
1470
|
/**
|
|
1152
1471
|
* Return a value from the cache. Will update the recency of the cache
|
|
1153
1472
|
* entry found.
|
|
@@ -1155,55 +1474,70 @@ export class LRUCache {
|
|
|
1155
1474
|
* If the key is not found, get() will return `undefined`.
|
|
1156
1475
|
*/
|
|
1157
1476
|
get(k, getOptions = {}) {
|
|
1477
|
+
const { status = metrics.hasSubscribers ? {} : undefined } = getOptions;
|
|
1478
|
+
getOptions.status = status;
|
|
1479
|
+
if (status) {
|
|
1480
|
+
status.op = 'get';
|
|
1481
|
+
status.key = k;
|
|
1482
|
+
}
|
|
1483
|
+
const result = this.#get(k, getOptions);
|
|
1484
|
+
if (status) {
|
|
1485
|
+
if (result !== undefined)
|
|
1486
|
+
status.value = result;
|
|
1487
|
+
if (metrics.hasSubscribers)
|
|
1488
|
+
metrics.publish(status);
|
|
1489
|
+
}
|
|
1490
|
+
return result;
|
|
1491
|
+
}
|
|
1492
|
+
#get(k, getOptions = {}) {
|
|
1158
1493
|
const { allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet, status, } = getOptions;
|
|
1159
1494
|
const index = this.#keyMap.get(k);
|
|
1160
|
-
if (index
|
|
1161
|
-
const value = this.#valList[index];
|
|
1162
|
-
const fetching = this.#isBackgroundFetch(value);
|
|
1495
|
+
if (index === undefined) {
|
|
1163
1496
|
if (status)
|
|
1164
|
-
|
|
1165
|
-
|
|
1497
|
+
status.get = 'miss';
|
|
1498
|
+
return undefined;
|
|
1499
|
+
}
|
|
1500
|
+
const value = this.#valList[index];
|
|
1501
|
+
const fetching = this.#isBackgroundFetch(value);
|
|
1502
|
+
if (status)
|
|
1503
|
+
this.#statusTTL(status, index);
|
|
1504
|
+
if (this.#isStale(index)) {
|
|
1505
|
+
// delete only if not an in-flight background fetch
|
|
1506
|
+
if (!fetching) {
|
|
1507
|
+
if (!noDeleteOnStaleGet) {
|
|
1508
|
+
this.#delete(k, 'expire');
|
|
1509
|
+
}
|
|
1166
1510
|
if (status)
|
|
1167
1511
|
status.get = 'stale';
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
if (!noDeleteOnStaleGet) {
|
|
1171
|
-
this.delete(k);
|
|
1172
|
-
}
|
|
1173
|
-
if (status && allowStale)
|
|
1174
|
-
status.returnedStale = true;
|
|
1175
|
-
return allowStale ? value : undefined;
|
|
1176
|
-
}
|
|
1177
|
-
else {
|
|
1178
|
-
if (status &&
|
|
1179
|
-
allowStale &&
|
|
1180
|
-
value.__staleWhileFetching !== undefined) {
|
|
1512
|
+
if (allowStale) {
|
|
1513
|
+
if (status)
|
|
1181
1514
|
status.returnedStale = true;
|
|
1182
|
-
|
|
1183
|
-
return allowStale ? value.__staleWhileFetching : undefined;
|
|
1515
|
+
return value;
|
|
1184
1516
|
}
|
|
1517
|
+
return undefined;
|
|
1185
1518
|
}
|
|
1186
|
-
|
|
1519
|
+
if (status)
|
|
1520
|
+
status.get = 'stale-fetching';
|
|
1521
|
+
if (allowStale && value.__staleWhileFetching !== undefined) {
|
|
1187
1522
|
if (status)
|
|
1188
|
-
status.
|
|
1189
|
-
|
|
1190
|
-
// it's not stale, which means this isn't a staleWhileRefetching.
|
|
1191
|
-
// If it's not stale, and fetching, AND has a __staleWhileFetching
|
|
1192
|
-
// value, then that means the user fetched with {forceRefresh:true},
|
|
1193
|
-
// so it's safe to return that value.
|
|
1194
|
-
if (fetching) {
|
|
1195
|
-
return value.__staleWhileFetching;
|
|
1196
|
-
}
|
|
1197
|
-
this.#moveToTail(index);
|
|
1198
|
-
if (updateAgeOnGet) {
|
|
1199
|
-
this.#updateItemAge(index);
|
|
1200
|
-
}
|
|
1201
|
-
return value;
|
|
1523
|
+
status.returnedStale = true;
|
|
1524
|
+
return value.__staleWhileFetching;
|
|
1202
1525
|
}
|
|
1526
|
+
return undefined;
|
|
1203
1527
|
}
|
|
1204
|
-
|
|
1205
|
-
|
|
1528
|
+
// not stale
|
|
1529
|
+
if (status)
|
|
1530
|
+
status.get = fetching ? 'fetching' : 'hit';
|
|
1531
|
+
// if we're currently fetching it, we don't actually have it yet
|
|
1532
|
+
// it's not stale, which means this isn't a staleWhileRefetching.
|
|
1533
|
+
// If it's not stale, and fetching, AND has a __staleWhileFetching
|
|
1534
|
+
// value, then that means the user fetched with {forceRefresh:true},
|
|
1535
|
+
// so it's safe to return that value.
|
|
1536
|
+
this.#moveToTail(index);
|
|
1537
|
+
if (updateAgeOnGet) {
|
|
1538
|
+
this.#updateItemAge(index);
|
|
1206
1539
|
}
|
|
1540
|
+
return fetching ? value.__staleWhileFetching : value;
|
|
1207
1541
|
}
|
|
1208
1542
|
#connect(p, n) {
|
|
1209
1543
|
this.#prev[n] = p;
|
|
@@ -1231,16 +1565,31 @@ export class LRUCache {
|
|
|
1231
1565
|
}
|
|
1232
1566
|
/**
|
|
1233
1567
|
* Deletes a key out of the cache.
|
|
1568
|
+
*
|
|
1234
1569
|
* Returns true if the key was deleted, false otherwise.
|
|
1235
1570
|
*/
|
|
1236
1571
|
delete(k) {
|
|
1572
|
+
return this.#delete(k, 'delete');
|
|
1573
|
+
}
|
|
1574
|
+
#delete(k, reason) {
|
|
1575
|
+
if (metrics.hasSubscribers) {
|
|
1576
|
+
metrics.publish({
|
|
1577
|
+
op: 'delete',
|
|
1578
|
+
delete: reason,
|
|
1579
|
+
key: k,
|
|
1580
|
+
});
|
|
1581
|
+
}
|
|
1237
1582
|
let deleted = false;
|
|
1238
1583
|
if (this.#size !== 0) {
|
|
1239
1584
|
const index = this.#keyMap.get(k);
|
|
1240
1585
|
if (index !== undefined) {
|
|
1586
|
+
if (this.#autopurgeTimers?.[index]) {
|
|
1587
|
+
clearTimeout(this.#autopurgeTimers?.[index]);
|
|
1588
|
+
this.#autopurgeTimers[index] = undefined;
|
|
1589
|
+
}
|
|
1241
1590
|
deleted = true;
|
|
1242
1591
|
if (this.#size === 1) {
|
|
1243
|
-
this
|
|
1592
|
+
this.#clear(reason);
|
|
1244
1593
|
}
|
|
1245
1594
|
else {
|
|
1246
1595
|
this.#removeItemSize(index);
|
|
@@ -1250,10 +1599,10 @@ export class LRUCache {
|
|
|
1250
1599
|
}
|
|
1251
1600
|
else if (this.#hasDispose || this.#hasDisposeAfter) {
|
|
1252
1601
|
if (this.#hasDispose) {
|
|
1253
|
-
this.#dispose?.(v, k,
|
|
1602
|
+
this.#dispose?.(v, k, reason);
|
|
1254
1603
|
}
|
|
1255
1604
|
if (this.#hasDisposeAfter) {
|
|
1256
|
-
this.#disposed?.push([v, k,
|
|
1605
|
+
this.#disposed?.push([v, k, reason]);
|
|
1257
1606
|
}
|
|
1258
1607
|
}
|
|
1259
1608
|
this.#keyMap.delete(k);
|
|
@@ -1266,8 +1615,10 @@ export class LRUCache {
|
|
|
1266
1615
|
this.#head = this.#next[index];
|
|
1267
1616
|
}
|
|
1268
1617
|
else {
|
|
1269
|
-
|
|
1270
|
-
this.#
|
|
1618
|
+
const pi = this.#prev[index];
|
|
1619
|
+
this.#next[pi] = this.#next[index];
|
|
1620
|
+
const ni = this.#next[index];
|
|
1621
|
+
this.#prev[ni] = this.#prev[index];
|
|
1271
1622
|
}
|
|
1272
1623
|
this.#size--;
|
|
1273
1624
|
this.#free.push(index);
|
|
@@ -1287,6 +1638,9 @@ export class LRUCache {
|
|
|
1287
1638
|
* Clear the cache entirely, throwing away all values.
|
|
1288
1639
|
*/
|
|
1289
1640
|
clear() {
|
|
1641
|
+
return this.#clear('delete');
|
|
1642
|
+
}
|
|
1643
|
+
#clear(reason) {
|
|
1290
1644
|
for (const index of this.#rindexes({ allowStale: true })) {
|
|
1291
1645
|
const v = this.#valList[index];
|
|
1292
1646
|
if (this.#isBackgroundFetch(v)) {
|
|
@@ -1295,10 +1649,10 @@ export class LRUCache {
|
|
|
1295
1649
|
else {
|
|
1296
1650
|
const k = this.#keyList[index];
|
|
1297
1651
|
if (this.#hasDispose) {
|
|
1298
|
-
this.#dispose?.(v, k,
|
|
1652
|
+
this.#dispose?.(v, k, reason);
|
|
1299
1653
|
}
|
|
1300
1654
|
if (this.#hasDisposeAfter) {
|
|
1301
|
-
this.#disposed?.push([v, k,
|
|
1655
|
+
this.#disposed?.push([v, k, reason]);
|
|
1302
1656
|
}
|
|
1303
1657
|
}
|
|
1304
1658
|
}
|
|
@@ -1308,6 +1662,11 @@ export class LRUCache {
|
|
|
1308
1662
|
if (this.#ttls && this.#starts) {
|
|
1309
1663
|
this.#ttls.fill(0);
|
|
1310
1664
|
this.#starts.fill(0);
|
|
1665
|
+
for (const t of this.#autopurgeTimers ?? []) {
|
|
1666
|
+
if (t !== undefined)
|
|
1667
|
+
clearTimeout(t);
|
|
1668
|
+
}
|
|
1669
|
+
this.#autopurgeTimers?.fill(undefined);
|
|
1311
1670
|
}
|
|
1312
1671
|
if (this.#sizes) {
|
|
1313
1672
|
this.#sizes.fill(0);
|
|
@@ -1326,5 +1685,4 @@ export class LRUCache {
|
|
|
1326
1685
|
}
|
|
1327
1686
|
}
|
|
1328
1687
|
}
|
|
1329
|
-
export default LRUCache;
|
|
1330
1688
|
//# sourceMappingURL=index.js.map
|