@neezco/cache 0.5.0 → 0.7.0

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.
@@ -1,4 +1,5 @@
1
- //#region rolldown:runtime
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ //#region \0rolldown/runtime.js
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -26,9 +27,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
27
 
27
28
  //#endregion
28
29
  let fs = require("fs");
29
- fs = __toESM(fs);
30
+ fs = __toESM(fs, 1);
30
31
  let v8 = require("v8");
31
- v8 = __toESM(v8);
32
+ v8 = __toESM(v8, 1);
32
33
  let perf_hooks = require("perf_hooks");
33
34
 
34
35
  //#region src/cache/clear.ts
@@ -61,11 +62,6 @@ const ONE_MINUTE = 60 * ONE_SECOND;
61
62
  */
62
63
  const DEFAULT_TTL = 30 * ONE_MINUTE;
63
64
  /**
64
- * Default stale window in milliseconds after expiration.
65
- * Allows serving slightly outdated data while fetching fresh data.
66
- */
67
- const DEFAULT_STALE_WINDOW = 0;
68
- /**
69
65
  * Maximum number of entries the cache can hold.
70
66
  * Beyond this limit, new entries are ignored.
71
67
  */
@@ -89,15 +85,9 @@ const DEFAULT_MAX_MEMORY_SIZE = Infinity;
89
85
  const MAX_KEYS_PER_BATCH = 1e3;
90
86
  /**
91
87
  * Minimal expired ratio enforced during sweeps.
92
- * Ensures control sweeps run above {@link EXPIRED_RATIO_MEMORY_THRESHOLD}.
93
88
  */
94
89
  const MINIMAL_EXPIRED_RATIO = .05;
95
90
  /**
96
- * Memory usage threshold (normalized 0–1) triggering control sweeps.
97
- * At or above this level, sweeping becomes more aggressive.
98
- */
99
- const EXPIRED_RATIO_MEMORY_THRESHOLD = .8;
100
- /**
101
91
  * Maximum allowed expired ratio when memory usage is low.
102
92
  * Upper bound for interpolation with MINIMAL_EXPIRED_RATIO.
103
93
  * Recommended range: `0.3 – 0.5` .
@@ -115,21 +105,6 @@ const DEFAULT_MAX_EXPIRED_RATIO = .4;
115
105
  */
116
106
  const OPTIMAL_SWEEP_INTERVAL = 2 * ONE_SECOND;
117
107
  /**
118
- * Worst-case interval in milliseconds between sweeps.
119
- * Used when system load is high or metrics unavailable.
120
- */
121
- const WORST_SWEEP_INTERVAL = 200;
122
- /**
123
- * Maximum time budget in milliseconds for sweep operations.
124
- * Prevents sweeping from consuming excessive CPU during high load.
125
- */
126
- const WORST_SWEEP_TIME_BUDGET = 40;
127
- /**
128
- * Optimal time budget in milliseconds for each sweep cycle.
129
- * Used when performance metrics are not available or unreliable.
130
- */
131
- const OPTIMAL_SWEEP_TIME_BUDGET_IF_NOTE_METRICS_AVAILABLE = 15;
132
- /**
133
108
  * ===================================================================
134
109
  * Memory Management
135
110
  * Process limits and memory-safe thresholds.
@@ -142,18 +117,6 @@ const OPTIMAL_SWEEP_TIME_BUDGET_IF_NOTE_METRICS_AVAILABLE = 15;
142
117
  */
143
118
  const DEFAULT_MAX_PROCESS_MEMORY_MB = 1024;
144
119
  /**
145
- * ===================================================================
146
- * System Utilization Weights
147
- * Balance how memory, CPU, and event-loop pressure influence sweep behavior.
148
- * Sum of all weights: 10 + 8.5 + 6.5 = 25
149
- * ===================================================================
150
- */
151
- /**
152
- * Weight applied to memory utilization in sweep calculations.
153
- * Higher weight = memory pressure has more influence on sweep aggressiveness.
154
- */
155
- const DEFAULT_MEMORY_WEIGHT = 10;
156
- /**
157
120
  * Weight applied to CPU utilization in sweep calculations.
158
121
  * Combined with event-loop weight to balance CPU-related pressure.
159
122
  */
@@ -164,22 +127,6 @@ const DEFAULT_CPU_WEIGHT = 8.5;
164
127
  */
165
128
  const DEFAULT_LOOP_WEIGHT = 6.5;
166
129
  /**
167
- * Fallback behavior for stale purging on GET
168
- * when no resource limits are defined.
169
- *
170
- * In this scenario, threshold-based purging is disabled,
171
- * so GET operations do NOT purge stale entries.
172
- */
173
- const DEFAULT_PURGE_STALE_ON_GET_NO_LIMITS = false;
174
- /**
175
- * Fallback behavior for stale purging on SWEEP
176
- * when no resource limits are defined.
177
- *
178
- * In this scenario, threshold-based purging is disabled,
179
- * so SWEEP operations DO purge stale entries to prevent buildup.
180
- */
181
- const DEFAULT_PURGE_STALE_ON_SWEEP_NO_LIMITS = true;
182
- /**
183
130
  * Default threshold for purging stale entries on get operations (backend with limits).
184
131
  * Stale entries are purged when resource usage exceeds 80%.
185
132
  *
@@ -343,7 +290,7 @@ const resolvePurgeStaleOnGet = (config) => resolvePurgeMode(config.limits, {
343
290
  operation: "purgeStaleOnGet"
344
291
  }, {
345
292
  withLimits: DEFAULT_PURGE_STALE_ON_GET_THRESHOLD,
346
- withoutLimits: DEFAULT_PURGE_STALE_ON_GET_NO_LIMITS
293
+ withoutLimits: false
347
294
  }, config.userValue);
348
295
 
349
296
  //#endregion
@@ -592,7 +539,7 @@ function startMonitor() {
592
539
  callback(metrics) {
593
540
  _metrics = metrics;
594
541
  },
595
- interval: WORST_SWEEP_INTERVAL,
542
+ interval: 200,
596
543
  maxMemory: maxMemoryLimit
597
544
  });
598
545
  _monitorInstance.start();
@@ -649,10 +596,10 @@ function interpolate({ value, fromStart, fromEnd, toStart, toEnd }) {
649
596
  * @returns Interpolated sweep interval, time budget, and the ratio used.
650
597
  */
651
598
  const calculateOptimalSweepParams = (options) => {
652
- const { metrics, weights = {}, optimalSweepIntervalMs = OPTIMAL_SWEEP_INTERVAL, worstSweepIntervalMs = WORST_SWEEP_INTERVAL, worstSweepTimeBudgetMs = WORST_SWEEP_TIME_BUDGET } = options;
653
- const memoryWeight = weights.memory ?? DEFAULT_MEMORY_WEIGHT;
654
- const cpuWeight = weights.cpu ?? DEFAULT_CPU_WEIGHT;
655
- const loopWeight = weights.loop ?? DEFAULT_LOOP_WEIGHT;
599
+ const { metrics, weights = {}, optimalSweepIntervalMs = OPTIMAL_SWEEP_INTERVAL, worstSweepIntervalMs = 200, worstSweepTimeBudgetMs = 40 } = options;
600
+ const memoryWeight = weights.memory ?? 10;
601
+ const cpuWeight = weights.cpu ?? 8.5;
602
+ const loopWeight = weights.loop ?? 6.5;
656
603
  const memoryUtilization = metrics?.memory.utilization ?? 0;
657
604
  const cpuUtilizationRaw = metrics?.cpu.utilization ?? 0;
658
605
  const loopUtilizationRaw = metrics?.loop.utilization ?? 0;
@@ -700,38 +647,27 @@ const calculateOptimalSweepParams = (options) => {
700
647
  * or `undefined` if the cache is empty.
701
648
  */
702
649
  function _selectInstanceToSweep({ totalSweepWeight, batchSweep }) {
703
- let instanceToSweep = _instancesCache[0];
704
650
  if (totalSweepWeight <= 0) {
705
- if (batchSweep > _instancesCache.length) instanceToSweep = null;
706
- instanceToSweep = _instancesCache[batchSweep - 1];
707
- } else {
708
- let threshold = Math.random() * totalSweepWeight;
709
- for (const inst of _instancesCache) {
710
- threshold -= inst._sweepWeight;
711
- if (threshold <= 0) {
712
- instanceToSweep = inst;
713
- break;
714
- }
715
- }
651
+ if (batchSweep > _instancesCache.length) return null;
652
+ return _instancesCache[batchSweep - 1];
653
+ }
654
+ let threshold = Math.random() * totalSweepWeight;
655
+ for (const inst of _instancesCache) {
656
+ threshold -= inst._sweepWeight;
657
+ if (threshold <= 0) return inst;
716
658
  }
717
- return instanceToSweep;
659
+ return _instancesCache[0];
718
660
  }
719
661
 
720
662
  //#endregion
721
663
  //#region src/cache/delete.ts
722
- let DELETE_REASON = /* @__PURE__ */ function(DELETE_REASON$1) {
723
- DELETE_REASON$1["MANUAL"] = "manual";
724
- DELETE_REASON$1["EXPIRED"] = "expired";
725
- DELETE_REASON$1["STALE"] = "stale";
726
- return DELETE_REASON$1;
727
- }({});
728
664
  /**
729
665
  * Deletes a key from the cache.
730
666
  * @param state - The cache state.
731
667
  * @param key - The key.
732
668
  * @returns A boolean indicating whether the key was successfully deleted.
733
669
  */
734
- const deleteKey = (state, key, reason = DELETE_REASON.MANUAL) => {
670
+ const deleteKey = (state, key, reason = "manual") => {
735
671
  const onDelete = state.onDelete;
736
672
  const onExpire = state.onExpire;
737
673
  if (!onDelete && !onExpire) return state.store.delete(key);
@@ -739,7 +675,7 @@ const deleteKey = (state, key, reason = DELETE_REASON.MANUAL) => {
739
675
  if (!entry) return false;
740
676
  state.store.delete(key);
741
677
  state.onDelete?.(key, entry[1], reason);
742
- if (reason !== DELETE_REASON.MANUAL) state.onExpire?.(key, entry[1], reason);
678
+ if (reason !== "manual") state.onExpire?.(key, entry[1], reason);
743
679
  return true;
744
680
  };
745
681
 
@@ -748,14 +684,14 @@ const deleteKey = (state, key, reason = DELETE_REASON.MANUAL) => {
748
684
  /**
749
685
  * Entry status: fresh, stale, or expired.
750
686
  */
751
- let ENTRY_STATUS = /* @__PURE__ */ function(ENTRY_STATUS$1) {
687
+ let ENTRY_STATUS = /* @__PURE__ */ function(ENTRY_STATUS) {
752
688
  /** Valid and within TTL. */
753
- ENTRY_STATUS$1["FRESH"] = "fresh";
689
+ ENTRY_STATUS["FRESH"] = "fresh";
754
690
  /** Expired but within stale window; still served. */
755
- ENTRY_STATUS$1["STALE"] = "stale";
691
+ ENTRY_STATUS["STALE"] = "stale";
756
692
  /** Beyond stale window; not served. */
757
- ENTRY_STATUS$1["EXPIRED"] = "expired";
758
- return ENTRY_STATUS$1;
693
+ ENTRY_STATUS["EXPIRED"] = "expired";
694
+ return ENTRY_STATUS;
759
695
  }({});
760
696
 
761
697
  //#endregion
@@ -781,22 +717,22 @@ let ENTRY_STATUS = /* @__PURE__ */ function(ENTRY_STATUS$1) {
781
717
  function _statusFromTags(state, entry) {
782
718
  const entryCreatedAt = entry[0][0];
783
719
  let earliestTagStaleInvalidation = Infinity;
784
- let status = ENTRY_STATUS.FRESH;
720
+ let status = "fresh";
785
721
  const tags = entry[2];
786
722
  if (tags) for (const tag of tags) {
787
723
  const ts = state._tags.get(tag);
788
724
  if (!ts) continue;
789
725
  const [tagExpiredAt, tagStaleSinceAt] = ts;
790
726
  if (tagExpiredAt >= entryCreatedAt) {
791
- status = ENTRY_STATUS.EXPIRED;
727
+ status = "expired";
792
728
  break;
793
729
  }
794
730
  if (tagStaleSinceAt >= entryCreatedAt) {
795
731
  if (tagStaleSinceAt < earliestTagStaleInvalidation) earliestTagStaleInvalidation = tagStaleSinceAt;
796
- status = ENTRY_STATUS.STALE;
732
+ status = "stale";
797
733
  }
798
734
  }
799
- return [status, status === ENTRY_STATUS.STALE ? earliestTagStaleInvalidation : 0];
735
+ return [status, status === "stale" ? earliestTagStaleInvalidation : 0];
800
736
  }
801
737
 
802
738
  //#endregion
@@ -819,12 +755,12 @@ function _statusFromTags(state, entry) {
819
755
  function computeEntryStatus(state, entry, now) {
820
756
  const [__createdAt, expiresAt, staleExpiresAt] = entry[0];
821
757
  const [tagStatus, earliestTagStaleInvalidation] = _statusFromTags(state, entry);
822
- if (tagStatus === ENTRY_STATUS.EXPIRED) return ENTRY_STATUS.EXPIRED;
758
+ if (tagStatus === "expired") return "expired";
823
759
  const windowStale = staleExpiresAt - expiresAt;
824
- if (tagStatus === ENTRY_STATUS.STALE && staleExpiresAt > 0 && now < earliestTagStaleInvalidation + windowStale && now <= staleExpiresAt) return ENTRY_STATUS.STALE;
825
- if (now < expiresAt) return ENTRY_STATUS.FRESH;
826
- if (staleExpiresAt > 0 && now < staleExpiresAt) return ENTRY_STATUS.STALE;
827
- return ENTRY_STATUS.EXPIRED;
760
+ if (tagStatus === "stale" && staleExpiresAt > 0 && now < earliestTagStaleInvalidation + windowStale && now <= staleExpiresAt) return "stale";
761
+ if (now < expiresAt) return "fresh";
762
+ if (staleExpiresAt > 0 && now < staleExpiresAt) return "stale";
763
+ return "expired";
828
764
  }
829
765
  /**
830
766
  * Determines whether a cache entry is fresh.
@@ -842,8 +778,8 @@ function computeEntryStatus(state, entry, now) {
842
778
  * @returns True if the entry is fresh.
843
779
  */
844
780
  const isFresh = (state, entry, now) => {
845
- if (typeof entry === "string") return entry === ENTRY_STATUS.FRESH;
846
- return computeEntryStatus(state, entry, now) === ENTRY_STATUS.FRESH;
781
+ if (typeof entry === "string") return entry === "fresh";
782
+ return computeEntryStatus(state, entry, now) === "fresh";
847
783
  };
848
784
  /**
849
785
  * Determines whether a cache entry is stale.
@@ -861,8 +797,8 @@ const isFresh = (state, entry, now) => {
861
797
  * @returns True if the entry is stale.
862
798
  */
863
799
  const isStale = (state, entry, now) => {
864
- if (typeof entry === "string") return entry === ENTRY_STATUS.STALE;
865
- return computeEntryStatus(state, entry, now) === ENTRY_STATUS.STALE;
800
+ if (typeof entry === "string") return entry === "stale";
801
+ return computeEntryStatus(state, entry, now) === "stale";
866
802
  };
867
803
  /**
868
804
  * Determines whether a cache entry is expired.
@@ -880,8 +816,8 @@ const isStale = (state, entry, now) => {
880
816
  * @returns True if the entry is expired.
881
817
  */
882
818
  const isExpired = (state, entry, now) => {
883
- if (typeof entry === "string") return entry === ENTRY_STATUS.EXPIRED;
884
- return computeEntryStatus(state, entry, now) === ENTRY_STATUS.EXPIRED;
819
+ if (typeof entry === "string") return entry === "expired";
820
+ return computeEntryStatus(state, entry, now) === "expired";
885
821
  };
886
822
 
887
823
  //#endregion
@@ -953,7 +889,7 @@ const shouldPurge = (mode, state, purgeContext) => {
953
889
  if (mode === false) return false;
954
890
  if (mode === true) return true;
955
891
  const userThreshold = Number(mode);
956
- const defaultPurge = purgeContext === "sweep" ? DEFAULT_PURGE_STALE_ON_SWEEP_NO_LIMITS : DEFAULT_PURGE_STALE_ON_GET_NO_LIMITS;
892
+ const defaultPurge = purgeContext === "sweep" ? true : false;
957
893
  if (Number.isNaN(userThreshold)) return defaultPurge;
958
894
  const usage = computeResourceUsage(state);
959
895
  if (!usage) return defaultPurge;
@@ -971,9 +907,11 @@ const shouldPurge = (mode, state, purgeContext) => {
971
907
  */
972
908
  function _sweepOnce(state, _maxKeysPerBatch = MAX_KEYS_PER_BATCH) {
973
909
  if (!state._sweepIter) state._sweepIter = state.store.entries();
910
+ const now = Date.now();
974
911
  let processed = 0;
975
912
  let expiredCount = 0;
976
913
  let staleCount = 0;
914
+ const shouldPurgeStale = shouldPurge(state.purgeStaleOnSweep, state, "sweep");
977
915
  for (let i = 0; i < _maxKeysPerBatch; i++) {
978
916
  const next = state._sweepIter.next();
979
917
  if (next.done) {
@@ -982,22 +920,20 @@ function _sweepOnce(state, _maxKeysPerBatch = MAX_KEYS_PER_BATCH) {
982
920
  }
983
921
  processed += 1;
984
922
  const [key, entry] = next.value;
985
- const now = Date.now();
986
923
  const status = computeEntryStatus(state, entry, now);
987
924
  if (isExpired(state, status, now)) {
988
- deleteKey(state, key, DELETE_REASON.EXPIRED);
925
+ deleteKey(state, key, "expired");
989
926
  expiredCount += 1;
990
927
  } else if (isStale(state, status, now)) {
991
928
  staleCount += 1;
992
- if (shouldPurge(state.purgeStaleOnSweep, state, "sweep")) deleteKey(state, key, DELETE_REASON.STALE);
929
+ if (shouldPurgeStale) deleteKey(state, key, "stale");
993
930
  }
994
931
  }
995
- const expiredStaleCount = shouldPurge(state.purgeStaleOnSweep, state, "sweep") ? staleCount : 0;
996
932
  return {
997
933
  processed,
998
934
  expiredCount,
999
935
  staleCount,
1000
- ratio: processed > 0 ? (expiredCount + expiredStaleCount) / processed : 0
936
+ ratio: processed > 0 ? (expiredCount + (shouldPurgeStale ? staleCount : 0)) / processed : 0
1001
937
  };
1002
938
  }
1003
939
 
@@ -1008,8 +944,8 @@ function _sweepOnce(state, _maxKeysPerBatch = MAX_KEYS_PER_BATCH) {
1008
944
  *
1009
945
  * This function interpolates between `maxAllowExpiredRatio` and `MINIMAL_EXPIRED_RATIO`
1010
946
  * depending on the memory usage reported by `_metrics`. At low memory usage (0%),
1011
- * the optimal ratio equals `maxAllowExpiredRatio`. As memory usage approaches or exceeds
1012
- * 80% of the memory limit, the optimal ratio decreases toward `MINIMAL_EXPIRED_RATIO`.
947
+ * the optimal ratio equals `maxAllowExpiredRatio`. At high memory usage
948
+ * the optimal ratio decreases toward `MINIMAL_EXPIRED_RATIO`.
1013
949
  *
1014
950
  * @param maxAllowExpiredRatio - The maximum allowed expired ratio at minimal memory usage.
1015
951
  * Defaults to `DEFAULT_MAX_EXPIRED_RATIO`.
@@ -1019,7 +955,7 @@ function calculateOptimalMaxExpiredRatio(maxAllowExpiredRatio = DEFAULT_MAX_EXPI
1019
955
  const optimalExpiredRatio = interpolate({
1020
956
  value: _metrics?.memory.utilization ?? 0,
1021
957
  fromStart: 0,
1022
- fromEnd: EXPIRED_RATIO_MEMORY_THRESHOLD,
958
+ fromEnd: 1,
1023
959
  toStart: maxAllowExpiredRatio,
1024
960
  toEnd: MINIMAL_EXPIRED_RATIO
1025
961
  });
@@ -1038,8 +974,6 @@ function calculateOptimalMaxExpiredRatio(maxAllowExpiredRatio = DEFAULT_MAX_EXPI
1038
974
  * This function complements (`_selectInstanceToSweep`), which is responsible
1039
975
  * for selecting the correct instance based on the weights assigned here.
1040
976
  *
1041
- * ---
1042
- *
1043
977
  * ### Sweep systems:
1044
978
  * 1. **Normal sweep**
1045
979
  * - Runs whenever the percentage of expired keys exceeds the allowed threshold
@@ -1047,14 +981,7 @@ function calculateOptimalMaxExpiredRatio(maxAllowExpiredRatio = DEFAULT_MAX_EXPI
1047
981
  * - It is the main cleanup mechanism and is applied proportionally to the
1048
982
  * store size and the expired‑key ratio.
1049
983
  *
1050
- * 2. **Memoryconditioned sweep (control)**
1051
- * - Works exactly like the normal sweep, except it may run even when it
1052
- * normally wouldn’t.
1053
- * - Only activates under **high memory pressure**.
1054
- * - Serves as an additional control mechanism to adjust weights, keep the
1055
- * system updated, and help prevent memory overflows.
1056
- *
1057
- * 3. **Round‑robin sweep (minimal control)**
984
+ * 2. **Roundrobin sweep (minimal control)**
1058
985
  * - Always runs, even if the expired ratio is low or memory usage does not
1059
986
  * require it.
1060
987
  * - Processes a very small number of keys per instance, much smaller than
@@ -1062,16 +989,6 @@ function calculateOptimalMaxExpiredRatio(maxAllowExpiredRatio = DEFAULT_MAX_EXPI
1062
989
  * - Its main purpose is to ensure that all instances receive at least a
1063
990
  * periodic weight update and minimal expired‑key control.
1064
991
  *
1065
- * ---
1066
- * #### Important notes:
1067
- * - A minimum `MINIMAL_EXPIRED_RATIO` (e.g., 5%) is assumed to ensure that
1068
- * control sweeps can always run under high‑memory scenarios.
1069
- * - Even with a minimum ratio, the normal sweep and the memory‑conditioned sweep
1070
- * may **skip execution** if memory usage allows it and the expired ratio is
1071
- * below the optimal maximum.
1072
- * - The round‑robin sweep is never skipped: it always runs with a very small,
1073
- * almost imperceptible cost.
1074
- *
1075
992
  * @returns The total accumulated sweep weight across all cache instances.
1076
993
  */
1077
994
  function _updateWeightSweep() {
@@ -1081,14 +998,10 @@ function _updateWeightSweep() {
1081
998
  instCache._sweepWeight = 0;
1082
999
  continue;
1083
1000
  }
1084
- let expiredRatio = MINIMAL_EXPIRED_RATIO;
1085
- if (instCache._expiredRatio > MINIMAL_EXPIRED_RATIO) expiredRatio = instCache._expiredRatio;
1086
- {
1087
- const optimalMaxExpiredRatio = calculateOptimalMaxExpiredRatio(instCache._maxAllowExpiredRatio);
1088
- if (expiredRatio <= optimalMaxExpiredRatio) {
1089
- instCache._sweepWeight = 0;
1090
- continue;
1091
- }
1001
+ const expiredRatio = instCache._expiredRatio;
1002
+ if (expiredRatio <= calculateOptimalMaxExpiredRatio(instCache._maxAllowExpiredRatio)) {
1003
+ instCache._sweepWeight = 0;
1004
+ continue;
1092
1005
  }
1093
1006
  instCache._sweepWeight = instCache.store.size * expiredRatio;
1094
1007
  totalSweepWeight += instCache._sweepWeight;
@@ -1115,7 +1028,7 @@ const sweep = async (state, utilities = {}) => {
1115
1028
  const { schedule = defaultSchedule, yieldFn = defaultYieldFn, now = Date.now(), runOnlyOne = false } = utilities;
1116
1029
  const startTime = now;
1117
1030
  let sweepIntervalMs = OPTIMAL_SWEEP_INTERVAL;
1118
- let sweepTimeBudgetMs = OPTIMAL_SWEEP_TIME_BUDGET_IF_NOTE_METRICS_AVAILABLE;
1031
+ let sweepTimeBudgetMs = 15;
1119
1032
  if (_metrics) ({sweepIntervalMs, sweepTimeBudgetMs} = calculateOptimalSweepParams({ metrics: _metrics }));
1120
1033
  const totalSweepWeight = _updateWeightSweep();
1121
1034
  const currentExpiredRatios = [];
@@ -1153,7 +1066,7 @@ const _instancesCache = [];
1153
1066
  * @returns The initial cache state.
1154
1067
  */
1155
1068
  const createCache = (options = {}) => {
1156
- const { onExpire, onDelete, defaultTtl = DEFAULT_TTL, maxSize = DEFAULT_MAX_SIZE, maxMemorySize = DEFAULT_MAX_MEMORY_SIZE, _maxAllowExpiredRatio = DEFAULT_MAX_EXPIRED_RATIO, defaultStaleWindow = DEFAULT_STALE_WINDOW, purgeStaleOnGet, purgeStaleOnSweep, purgeResourceMetric, _autoStartSweep = true } = options;
1069
+ const { onExpire, onDelete, defaultTtl = DEFAULT_TTL, maxSize = DEFAULT_MAX_SIZE, maxMemorySize = DEFAULT_MAX_MEMORY_SIZE, _maxAllowExpiredRatio = DEFAULT_MAX_EXPIRED_RATIO, defaultStaleWindow = 0, purgeStaleOnGet, purgeStaleOnSweep, purgeResourceMetric, _autoStartSweep = true } = options;
1157
1070
  _instanceCount++;
1158
1071
  if (_instanceCount > INSTANCE_WARNING_THRESHOLD) console.warn(`Too many instances detected (${_instanceCount}). This may indicate a configuration issue; consider minimizing instance creation or grouping keys by expected expiration ranges. See the documentation: https://github.com/neezco/cache/docs/getting-started.md`);
1159
1072
  const resolvedPurgeResourceMetric = purgeResourceMetric ?? resolvePurgeResourceMetric({
@@ -1222,10 +1135,10 @@ const getWithStatus = (state, key, purgeMode, now = Date.now()) => {
1222
1135
  const status = computeEntryStatus(state, entry, now);
1223
1136
  if (isFresh(state, status, now)) return [status, entry];
1224
1137
  if (isStale(state, status, now)) {
1225
- if (shouldPurge(purgeMode ?? state.purgeStaleOnGet, state, "get")) deleteKey(state, key, DELETE_REASON.STALE);
1138
+ if (shouldPurge(purgeMode ?? state.purgeStaleOnGet, state, "get")) deleteKey(state, key, "stale");
1226
1139
  return [status, entry];
1227
1140
  }
1228
- deleteKey(state, key, DELETE_REASON.EXPIRED);
1141
+ deleteKey(state, key, "expired");
1229
1142
  return [status, void 0];
1230
1143
  };
1231
1144
  /**