@adaptic/utils 0.0.376 → 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.mjs CHANGED
@@ -4225,6 +4225,12 @@ class Queue {
4225
4225
 
4226
4226
  this.#head = this.#head.next;
4227
4227
  this.#size--;
4228
+
4229
+ // Clean up tail reference when queue becomes empty
4230
+ if (!this.#head) {
4231
+ this.#tail = undefined;
4232
+ }
4233
+
4228
4234
  return current.value;
4229
4235
  }
4230
4236
 
@@ -13841,6 +13847,7 @@ class LRUCache {
13841
13847
  #sizes;
13842
13848
  #starts;
13843
13849
  #ttls;
13850
+ #autopurgeTimers;
13844
13851
  #hasDispose;
13845
13852
  #hasFetchMethod;
13846
13853
  #hasDisposeAfter;
@@ -13859,6 +13866,7 @@ class LRUCache {
13859
13866
  // properties
13860
13867
  starts: c.#starts,
13861
13868
  ttls: c.#ttls,
13869
+ autopurgeTimers: c.#autopurgeTimers,
13862
13870
  sizes: c.#sizes,
13863
13871
  keyMap: c.#keyMap,
13864
13872
  keyList: c.#keyList,
@@ -13960,13 +13968,11 @@ class LRUCache {
13960
13968
  throw new TypeError('sizeCalculation set to non-function');
13961
13969
  }
13962
13970
  }
13963
- if (memoMethod !== undefined &&
13964
- typeof memoMethod !== 'function') {
13971
+ if (memoMethod !== undefined && typeof memoMethod !== 'function') {
13965
13972
  throw new TypeError('memoMethod must be a function if defined');
13966
13973
  }
13967
13974
  this.#memoMethod = memoMethod;
13968
- if (fetchMethod !== undefined &&
13969
- typeof fetchMethod !== 'function') {
13975
+ if (fetchMethod !== undefined && typeof fetchMethod !== 'function') {
13970
13976
  throw new TypeError('fetchMethod must be a function if specified');
13971
13977
  }
13972
13978
  this.#fetchMethod = fetchMethod;
@@ -14021,9 +14027,7 @@ class LRUCache {
14021
14027
  this.updateAgeOnGet = !!updateAgeOnGet;
14022
14028
  this.updateAgeOnHas = !!updateAgeOnHas;
14023
14029
  this.ttlResolution =
14024
- isPosInt(ttlResolution) || ttlResolution === 0 ?
14025
- ttlResolution
14026
- : 1;
14030
+ isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1;
14027
14031
  this.ttlAutopurge = !!ttlAutopurge;
14028
14032
  this.ttl = ttl || 0;
14029
14033
  if (this.ttl) {
@@ -14058,10 +14062,21 @@ class LRUCache {
14058
14062
  const starts = new ZeroArray(this.#max);
14059
14063
  this.#ttls = ttls;
14060
14064
  this.#starts = starts;
14065
+ const purgeTimers = this.ttlAutopurge ?
14066
+ new Array(this.#max)
14067
+ : undefined;
14068
+ this.#autopurgeTimers = purgeTimers;
14061
14069
  this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
14062
14070
  starts[index] = ttl !== 0 ? start : 0;
14063
14071
  ttls[index] = ttl;
14064
- if (ttl !== 0 && this.ttlAutopurge) {
14072
+ // clear out the purge timer if we're setting TTL to 0, and
14073
+ // previously had a ttl purge timer running, so it doesn't
14074
+ // fire unnecessarily.
14075
+ if (purgeTimers?.[index]) {
14076
+ clearTimeout(purgeTimers[index]);
14077
+ purgeTimers[index] = undefined;
14078
+ }
14079
+ if (ttl !== 0 && purgeTimers) {
14065
14080
  const t = setTimeout(() => {
14066
14081
  if (this.#isStale(index)) {
14067
14082
  this.#delete(this.#keyList[index], 'expire');
@@ -14073,6 +14088,7 @@ class LRUCache {
14073
14088
  t.unref();
14074
14089
  }
14075
14090
  /* c8 ignore stop */
14091
+ purgeTimers[index] = t;
14076
14092
  }
14077
14093
  };
14078
14094
  this.#updateItemAge = index => {
@@ -14264,8 +14280,7 @@ class LRUCache {
14264
14280
  *keys() {
14265
14281
  for (const i of this.#indexes()) {
14266
14282
  const k = this.#keyList[i];
14267
- if (k !== undefined &&
14268
- !this.#isBackgroundFetch(this.#valList[i])) {
14283
+ if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
14269
14284
  yield k;
14270
14285
  }
14271
14286
  }
@@ -14279,8 +14294,7 @@ class LRUCache {
14279
14294
  *rkeys() {
14280
14295
  for (const i of this.#rindexes()) {
14281
14296
  const k = this.#keyList[i];
14282
- if (k !== undefined &&
14283
- !this.#isBackgroundFetch(this.#valList[i])) {
14297
+ if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
14284
14298
  yield k;
14285
14299
  }
14286
14300
  }
@@ -14292,8 +14306,7 @@ class LRUCache {
14292
14306
  *values() {
14293
14307
  for (const i of this.#indexes()) {
14294
14308
  const v = this.#valList[i];
14295
- if (v !== undefined &&
14296
- !this.#isBackgroundFetch(this.#valList[i])) {
14309
+ if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
14297
14310
  yield this.#valList[i];
14298
14311
  }
14299
14312
  }
@@ -14307,8 +14320,7 @@ class LRUCache {
14307
14320
  *rvalues() {
14308
14321
  for (const i of this.#rindexes()) {
14309
14322
  const v = this.#valList[i];
14310
- if (v !== undefined &&
14311
- !this.#isBackgroundFetch(this.#valList[i])) {
14323
+ if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {
14312
14324
  yield this.#valList[i];
14313
14325
  }
14314
14326
  }
@@ -14666,6 +14678,10 @@ class LRUCache {
14666
14678
  }
14667
14679
  }
14668
14680
  this.#removeItemSize(head);
14681
+ if (this.#autopurgeTimers?.[head]) {
14682
+ clearTimeout(this.#autopurgeTimers[head]);
14683
+ this.#autopurgeTimers[head] = undefined;
14684
+ }
14669
14685
  // if we aren't about to use the index, then null these out
14670
14686
  if (free) {
14671
14687
  this.#keyList[head] = undefined;
@@ -14738,8 +14754,7 @@ class LRUCache {
14738
14754
  peek(k, peekOptions = {}) {
14739
14755
  const { allowStale = this.allowStale } = peekOptions;
14740
14756
  const index = this.#keyMap.get(k);
14741
- if (index === undefined ||
14742
- (!allowStale && this.#isStale(index))) {
14757
+ if (index === undefined || (!allowStale && this.#isStale(index))) {
14743
14758
  return;
14744
14759
  }
14745
14760
  const v = this.#valList[index];
@@ -14785,7 +14800,7 @@ class LRUCache {
14785
14800
  // cache and ignore the abort, or if it's still pending on this specific
14786
14801
  // background request, then write it to the cache.
14787
14802
  const vl = this.#valList[index];
14788
- if (vl === p || ignoreAbort && updateCache && vl === undefined) {
14803
+ if (vl === p || (ignoreAbort && updateCache && vl === undefined)) {
14789
14804
  if (v === undefined) {
14790
14805
  if (bf.__staleWhileFetching !== undefined) {
14791
14806
  this.#valList[index] = bf.__staleWhileFetching;
@@ -14849,8 +14864,7 @@ class LRUCache {
14849
14864
  // defer check until we are actually aborting,
14850
14865
  // so fetchMethod can override.
14851
14866
  ac.signal.addEventListener('abort', () => {
14852
- if (!options.ignoreFetchAbort ||
14853
- options.allowStaleOnFetchAbort) {
14867
+ if (!options.ignoreFetchAbort || options.allowStaleOnFetchAbort) {
14854
14868
  res(undefined);
14855
14869
  // when it eventually resolves, update the cache.
14856
14870
  if (options.allowStaleOnFetchAbort) {
@@ -15082,6 +15096,10 @@ class LRUCache {
15082
15096
  if (this.#size !== 0) {
15083
15097
  const index = this.#keyMap.get(k);
15084
15098
  if (index !== undefined) {
15099
+ if (this.#autopurgeTimers?.[index]) {
15100
+ clearTimeout(this.#autopurgeTimers?.[index]);
15101
+ this.#autopurgeTimers[index] = undefined;
15102
+ }
15085
15103
  deleted = true;
15086
15104
  if (this.#size === 1) {
15087
15105
  this.#clear(reason);
@@ -15157,6 +15175,11 @@ class LRUCache {
15157
15175
  if (this.#ttls && this.#starts) {
15158
15176
  this.#ttls.fill(0);
15159
15177
  this.#starts.fill(0);
15178
+ for (const t of this.#autopurgeTimers ?? []) {
15179
+ if (t !== undefined)
15180
+ clearTimeout(t);
15181
+ }
15182
+ this.#autopurgeTimers?.fill(undefined);
15160
15183
  }
15161
15184
  if (this.#sizes) {
15162
15185
  this.#sizes.fill(0);