@adaptic/utils 0.0.375 → 0.0.377

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/dist/index.cjs CHANGED
@@ -4247,6 +4247,12 @@ class Queue {
4247
4247
 
4248
4248
  this.#head = this.#head.next;
4249
4249
  this.#size--;
4250
+
4251
+ // Clean up tail reference when queue becomes empty
4252
+ if (!this.#head) {
4253
+ this.#tail = undefined;
4254
+ }
4255
+
4250
4256
  return current.value;
4251
4257
  }
4252
4258
 
@@ -13863,6 +13869,7 @@ class LRUCache {
13863
13869
  #sizes;
13864
13870
  #starts;
13865
13871
  #ttls;
13872
+ #autopurgeTimers;
13866
13873
  #hasDispose;
13867
13874
  #hasFetchMethod;
13868
13875
  #hasDisposeAfter;
@@ -13881,6 +13888,7 @@ class LRUCache {
13881
13888
  // properties
13882
13889
  starts: c.#starts,
13883
13890
  ttls: c.#ttls,
13891
+ autopurgeTimers: c.#autopurgeTimers,
13884
13892
  sizes: c.#sizes,
13885
13893
  keyMap: c.#keyMap,
13886
13894
  keyList: c.#keyList,
@@ -13982,13 +13990,11 @@ class LRUCache {
13982
13990
  throw new TypeError('sizeCalculation set to non-function');
13983
13991
  }
13984
13992
  }
13985
- if (memoMethod !== undefined &&
13986
- typeof memoMethod !== 'function') {
13993
+ if (memoMethod !== undefined && typeof memoMethod !== 'function') {
13987
13994
  throw new TypeError('memoMethod must be a function if defined');
13988
13995
  }
13989
13996
  this.#memoMethod = memoMethod;
13990
- if (fetchMethod !== undefined &&
13991
- typeof fetchMethod !== 'function') {
13997
+ if (fetchMethod !== undefined && typeof fetchMethod !== 'function') {
13992
13998
  throw new TypeError('fetchMethod must be a function if specified');
13993
13999
  }
13994
14000
  this.#fetchMethod = fetchMethod;
@@ -14043,9 +14049,7 @@ class LRUCache {
14043
14049
  this.updateAgeOnGet = !!updateAgeOnGet;
14044
14050
  this.updateAgeOnHas = !!updateAgeOnHas;
14045
14051
  this.ttlResolution =
14046
- isPosInt(ttlResolution) || ttlResolution === 0 ?
14047
- ttlResolution
14048
- : 1;
14052
+ isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1;
14049
14053
  this.ttlAutopurge = !!ttlAutopurge;
14050
14054
  this.ttl = ttl || 0;
14051
14055
  if (this.ttl) {
@@ -14080,10 +14084,21 @@ class LRUCache {
14080
14084
  const starts = new ZeroArray(this.#max);
14081
14085
  this.#ttls = ttls;
14082
14086
  this.#starts = starts;
14087
+ const purgeTimers = this.ttlAutopurge ?
14088
+ new Array(this.#max)
14089
+ : undefined;
14090
+ this.#autopurgeTimers = purgeTimers;
14083
14091
  this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
14084
14092
  starts[index] = ttl !== 0 ? start : 0;
14085
14093
  ttls[index] = ttl;
14086
- if (ttl !== 0 && this.ttlAutopurge) {
14094
+ // clear out the purge timer if we're setting TTL to 0, and
14095
+ // previously had a ttl purge timer running, so it doesn't
14096
+ // fire unnecessarily.
14097
+ if (purgeTimers?.[index]) {
14098
+ clearTimeout(purgeTimers[index]);
14099
+ purgeTimers[index] = undefined;
14100
+ }
14101
+ if (ttl !== 0 && purgeTimers) {
14087
14102
  const t = setTimeout(() => {
14088
14103
  if (this.#isStale(index)) {
14089
14104
  this.#delete(this.#keyList[index], 'expire');
@@ -14095,6 +14110,7 @@ class LRUCache {
14095
14110
  t.unref();
14096
14111
  }
14097
14112
  /* c8 ignore stop */
14113
+ purgeTimers[index] = t;
14098
14114
  }
14099
14115
  };
14100
14116
  this.#updateItemAge = index => {
@@ -14286,8 +14302,7 @@ class LRUCache {
14286
14302
  *keys() {
14287
14303
  for (const i of this.#indexes()) {
14288
14304
  const k = this.#keyList[i];
14289
- if (k !== undefined &&
14290
- !this.#isBackgroundFetch(this.#valList[i])) {
14305
+ if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
14291
14306
  yield k;
14292
14307
  }
14293
14308
  }
@@ -14301,8 +14316,7 @@ class LRUCache {
14301
14316
  *rkeys() {
14302
14317
  for (const i of this.#rindexes()) {
14303
14318
  const k = this.#keyList[i];
14304
- if (k !== undefined &&
14305
- !this.#isBackgroundFetch(this.#valList[i])) {
14319
+ if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
14306
14320
  yield k;
14307
14321
  }
14308
14322
  }
@@ -14314,8 +14328,7 @@ class LRUCache {
14314
14328
  *values() {
14315
14329
  for (const i of this.#indexes()) {
14316
14330
  const v = this.#valList[i];
14317
- if (v !== undefined &&
14318
- !this.#isBackgroundFetch(this.#valList[i])) {
14331
+ if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
14319
14332
  yield this.#valList[i];
14320
14333
  }
14321
14334
  }
@@ -14329,8 +14342,7 @@ class LRUCache {
14329
14342
  *rvalues() {
14330
14343
  for (const i of this.#rindexes()) {
14331
14344
  const v = this.#valList[i];
14332
- if (v !== undefined &&
14333
- !this.#isBackgroundFetch(this.#valList[i])) {
14345
+ if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
14334
14346
  yield this.#valList[i];
14335
14347
  }
14336
14348
  }
@@ -14688,6 +14700,10 @@ class LRUCache {
14688
14700
  }
14689
14701
  }
14690
14702
  this.#removeItemSize(head);
14703
+ if (this.#autopurgeTimers?.[head]) {
14704
+ clearTimeout(this.#autopurgeTimers[head]);
14705
+ this.#autopurgeTimers[head] = undefined;
14706
+ }
14691
14707
  // if we aren't about to use the index, then null these out
14692
14708
  if (free) {
14693
14709
  this.#keyList[head] = undefined;
@@ -14760,8 +14776,7 @@ class LRUCache {
14760
14776
  peek(k, peekOptions = {}) {
14761
14777
  const { allowStale = this.allowStale } = peekOptions;
14762
14778
  const index = this.#keyMap.get(k);
14763
- if (index === undefined ||
14764
- (!allowStale && this.#isStale(index))) {
14779
+ if (index === undefined || (!allowStale && this.#isStale(index))) {
14765
14780
  return;
14766
14781
  }
14767
14782
  const v = this.#valList[index];
@@ -14807,7 +14822,7 @@ class LRUCache {
14807
14822
  // cache and ignore the abort, or if it's still pending on this specific
14808
14823
  // background request, then write it to the cache.
14809
14824
  const vl = this.#valList[index];
14810
- if (vl === p || ignoreAbort && updateCache && vl === undefined) {
14825
+ if (vl === p || (ignoreAbort && updateCache && vl === undefined)) {
14811
14826
  if (v === undefined) {
14812
14827
  if (bf.__staleWhileFetching !== undefined) {
14813
14828
  this.#valList[index] = bf.__staleWhileFetching;
@@ -14871,8 +14886,7 @@ class LRUCache {
14871
14886
  // defer check until we are actually aborting,
14872
14887
  // so fetchMethod can override.
14873
14888
  ac.signal.addEventListener('abort', () => {
14874
- if (!options.ignoreFetchAbort ||
14875
- options.allowStaleOnFetchAbort) {
14889
+ if (!options.ignoreFetchAbort || options.allowStaleOnFetchAbort) {
14876
14890
  res(undefined);
14877
14891
  // when it eventually resolves, update the cache.
14878
14892
  if (options.allowStaleOnFetchAbort) {
@@ -15104,6 +15118,10 @@ class LRUCache {
15104
15118
  if (this.#size !== 0) {
15105
15119
  const index = this.#keyMap.get(k);
15106
15120
  if (index !== undefined) {
15121
+ if (this.#autopurgeTimers?.[index]) {
15122
+ clearTimeout(this.#autopurgeTimers?.[index]);
15123
+ this.#autopurgeTimers[index] = undefined;
15124
+ }
15107
15125
  deleted = true;
15108
15126
  if (this.#size === 1) {
15109
15127
  this.#clear(reason);
@@ -15179,6 +15197,11 @@ class LRUCache {
15179
15197
  if (this.#ttls && this.#starts) {
15180
15198
  this.#ttls.fill(0);
15181
15199
  this.#starts.fill(0);
15200
+ for (const t of this.#autopurgeTimers ?? []) {
15201
+ if (t !== undefined)
15202
+ clearTimeout(t);
15203
+ }
15204
+ this.#autopurgeTimers?.fill(undefined);
15182
15205
  }
15183
15206
  if (this.#sizes) {
15184
15207
  this.#sizes.fill(0);