actly 1.1.0 → 1.1.5

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.
Files changed (70) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +284 -52
  3. package/dist/core/act.cjs +183 -35
  4. package/dist/core/act.d.ts +81 -10
  5. package/dist/core/act.d.ts.map +1 -1
  6. package/dist/core/act.js +181 -35
  7. package/dist/core/act.js.map +1 -1
  8. package/dist/core/executor.cjs +19 -9
  9. package/dist/core/executor.d.ts +25 -5
  10. package/dist/core/executor.d.ts.map +1 -1
  11. package/dist/core/executor.js +19 -9
  12. package/dist/core/executor.js.map +1 -1
  13. package/dist/index.cjs +13 -3
  14. package/dist/index.d.ts +7 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +8 -4
  17. package/dist/index.js.map +1 -1
  18. package/dist/policies/cache.cjs +85 -21
  19. package/dist/policies/cache.d.ts +29 -7
  20. package/dist/policies/cache.d.ts.map +1 -1
  21. package/dist/policies/cache.js +85 -21
  22. package/dist/policies/cache.js.map +1 -1
  23. package/dist/policies/dedupe.cjs +68 -20
  24. package/dist/policies/dedupe.d.ts +38 -13
  25. package/dist/policies/dedupe.d.ts.map +1 -1
  26. package/dist/policies/dedupe.js +68 -20
  27. package/dist/policies/dedupe.js.map +1 -1
  28. package/dist/policies/retry.cjs +65 -25
  29. package/dist/policies/retry.d.ts +25 -2
  30. package/dist/policies/retry.d.ts.map +1 -1
  31. package/dist/policies/retry.js +65 -25
  32. package/dist/policies/retry.js.map +1 -1
  33. package/dist/policies/timeout.cjs +87 -17
  34. package/dist/policies/timeout.d.ts +28 -8
  35. package/dist/policies/timeout.d.ts.map +1 -1
  36. package/dist/policies/timeout.js +87 -17
  37. package/dist/policies/timeout.js.map +1 -1
  38. package/dist/state/store.cjs +9 -2
  39. package/dist/state/store.d.ts +9 -0
  40. package/dist/state/store.d.ts.map +1 -1
  41. package/dist/state/store.js +9 -2
  42. package/dist/state/store.js.map +1 -1
  43. package/dist/stores/base.cjs +4 -4
  44. package/dist/stores/base.d.ts +32 -56
  45. package/dist/stores/base.d.ts.map +1 -1
  46. package/dist/stores/base.js +4 -4
  47. package/dist/stores/base.js.map +1 -1
  48. package/dist/stores/memory.cjs +77 -28
  49. package/dist/stores/memory.d.ts +44 -23
  50. package/dist/stores/memory.d.ts.map +1 -1
  51. package/dist/stores/memory.js +77 -28
  52. package/dist/stores/memory.js.map +1 -1
  53. package/dist/types/index.d.ts +141 -36
  54. package/dist/types/index.d.ts.map +1 -1
  55. package/dist/utils/abort.cjs +142 -0
  56. package/dist/utils/abort.d.ts +55 -0
  57. package/dist/utils/abort.d.ts.map +1 -0
  58. package/dist/utils/abort.js +136 -0
  59. package/dist/utils/abort.js.map +1 -0
  60. package/dist/utils/backoff.cjs +43 -0
  61. package/dist/utils/backoff.d.ts +14 -0
  62. package/dist/utils/backoff.d.ts.map +1 -0
  63. package/dist/utils/backoff.js +41 -0
  64. package/dist/utils/backoff.js.map +1 -0
  65. package/dist/utils/validate.cjs +79 -0
  66. package/dist/utils/validate.d.ts +15 -0
  67. package/dist/utils/validate.d.ts.map +1 -0
  68. package/dist/utils/validate.js +72 -0
  69. package/dist/utils/validate.js.map +1 -0
  70. package/package.json +19 -37
@@ -5,17 +5,37 @@ function isUnrefable(t) {
5
5
  return typeof t.unref === 'function';
6
6
  }
7
7
  // ─── Implementation ───────────────────────────────────────────────────────────
8
+ /**
9
+ * Reference `SyncStateStore` implementation backed by a `Map`.
10
+ *
11
+ * # LRU semantics
12
+ *
13
+ * `Map` iteration order is insertion order, so we implement LRU by
14
+ * `delete` + `set` on every access — the most-recently-touched key ends up
15
+ * at the end of the iteration, and the oldest is `entries.keys().next().value`.
16
+ *
17
+ * # Expiry
18
+ *
19
+ * Lazy on `get()` / `has()`: expired entries are deleted when touched.
20
+ * Background sweep (optional) reclaims entries that are never re-read.
21
+ */
8
22
  class InMemoryStore {
23
+ _sync = true;
24
+ entries = new Map();
25
+ maxSize;
26
+ cleanupTimer;
9
27
  constructor(options = {}) {
10
- // Discriminant read by isSyncStore() in execute() to enforce the dedupe
11
- // constraint at runtime for JS callers who bypass TypeScript.
12
- this._sync = true;
13
- this.entries = new Map();
14
- const { autoCleanup = false, cleanupIntervalMs = 30000 } = options;
28
+ const { autoCleanup = false, cleanupIntervalMs = 30_000, maxSize = Number.POSITIVE_INFINITY, } = options;
29
+ if (!Number.isFinite(maxSize) || maxSize <= 0) {
30
+ // Infinity is allowed (unbounded); any other non-positive finite value
31
+ // is a programmer error.
32
+ if (maxSize !== Number.POSITIVE_INFINITY) {
33
+ throw new RangeError(`Actly: InMemoryStore maxSize must be a positive finite number or Infinity, got ${maxSize}`);
34
+ }
35
+ }
36
+ this.maxSize = maxSize;
15
37
  if (autoCleanup) {
16
38
  const timer = setInterval(() => this._sweep(), cleanupIntervalMs);
17
- // Prevent the interval from keeping the Node.js process alive when the
18
- // application has otherwise finished its work. Safe no-op in browsers.
19
39
  if (isUnrefable(timer))
20
40
  timer.unref();
21
41
  this.cleanupTimer = timer;
@@ -29,47 +49,71 @@ class InMemoryStore {
29
49
  this.entries.delete(key);
30
50
  return undefined;
31
51
  }
52
+ // LRU refresh: move to most-recent position.
53
+ // delete + set is the canonical pattern for reordering a Map.
54
+ this.entries.delete(key);
55
+ this.entries.set(key, entry);
32
56
  return entry.value;
33
57
  }
34
58
  set(key, value, ttlMs) {
35
- // ttlMs = 0 or undefined no expiry (sentinel null)
59
+ // Evict if at capacity AND adding a new key (updates don't grow size).
60
+ if (!this.entries.has(key) && this.entries.size >= this.maxSize) {
61
+ const oldest = this.entries.keys().next().value;
62
+ if (oldest !== undefined)
63
+ this.entries.delete(oldest);
64
+ }
36
65
  const expiresAt = ttlMs != null && ttlMs > 0 ? Date.now() + ttlMs : null;
66
+ // delete + set ensures the key is moved to the most-recent position
67
+ // even on update, keeping LRU order consistent.
68
+ this.entries.delete(key);
37
69
  this.entries.set(key, { value, expiresAt });
38
70
  }
39
71
  delete(key) {
40
72
  this.entries.delete(key);
41
73
  }
42
74
  has(key) {
43
- // Delegate to get() so expired entries are evicted on access.
44
- return this.get(key) !== undefined;
75
+ // Inline the expiry check to avoid the LRU side-effect of get().
76
+ // `has()` should be a pure query, not a touch.
77
+ const entry = this.entries.get(key);
78
+ if (!entry)
79
+ return false;
80
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
81
+ this.entries.delete(key);
82
+ return false;
83
+ }
84
+ return true;
45
85
  }
46
- /**
47
- * Remove all entries.
48
- * After this call, size() returns 0.
49
- */
50
86
  clear() {
51
87
  this.entries.clear();
52
88
  }
53
89
  /**
54
90
  * Return the count of live (non-expired) entries.
55
91
  *
56
- * Expired entries are evicted during the scan, so repeated calls are
57
- * slightly cheaper as the map self-prunes. O(n) in the number of entries.
92
+ * Pure query does NOT touch LRU order. Expired entries discovered during
93
+ * the scan are evicted opportunistically (they were already invisible to
94
+ * `get()`, so eviction has no observable effect beyond memory reclamation).
95
+ *
96
+ * Two-pass to avoid mutating the Map during iteration (spec-safe).
58
97
  */
59
98
  size() {
60
- // Evict expired entries as we scan — keeps the map tidy between sweeps
61
- // and ensures the returned count reflects only observable entries.
62
- for (const key of this.entries.keys())
63
- this.has(key);
64
- return this.entries.size;
99
+ const now = Date.now();
100
+ const expired = [];
101
+ let count = 0;
102
+ for (const [key, entry] of this.entries) {
103
+ if (entry.expiresAt !== null && entry.expiresAt <= now) {
104
+ expired.push(key);
105
+ }
106
+ else {
107
+ count++;
108
+ }
109
+ }
110
+ for (const key of expired)
111
+ this.entries.delete(key);
112
+ return count;
65
113
  }
66
114
  /**
67
115
  * Stop the background cleanup timer and release internal state.
68
116
  * Safe to call multiple times — subsequent calls are no-ops.
69
- *
70
- * Call destroy() when discarding a long-lived store instance to prevent
71
- * timer leaks. Stores without autoCleanup enabled have nothing to release,
72
- * but destroy() is safe to call on them regardless.
73
117
  */
74
118
  destroy() {
75
119
  if (this.cleanupTimer !== undefined) {
@@ -77,15 +121,20 @@ class InMemoryStore {
77
121
  this.cleanupTimer = undefined;
78
122
  }
79
123
  }
80
- // Sweep all entries and remove those past their expiry time.
81
- // Called by the autoCleanup interval not part of the public contract.
124
+ /**
125
+ * Sweep all entries and remove those past their expiry time.
126
+ * Called by the autoCleanup interval; not part of the public contract.
127
+ */
82
128
  _sweep() {
83
129
  const now = Date.now();
130
+ const expired = [];
84
131
  for (const [key, entry] of this.entries) {
85
132
  if (entry.expiresAt !== null && now > entry.expiresAt) {
86
- this.entries.delete(key);
133
+ expired.push(key);
87
134
  }
88
135
  }
136
+ for (const key of expired)
137
+ this.entries.delete(key);
89
138
  }
90
139
  }
91
140
  exports.InMemoryStore = InMemoryStore;
@@ -3,56 +3,77 @@ export interface InMemoryStoreOptions {
3
3
  /**
4
4
  * Periodically sweep and remove expired entries in the background.
5
5
  *
6
- * Disabled by default. The store evicts lazily on get()/has() access, which
7
- * is sufficient for most use cases. Enable autoCleanup when the store is
8
- * long-lived and accumulates many TTL'd entries that are never re-read — for
9
- * example, a server-side cache that receives write-heavy traffic with low
10
- * subsequent read rates.
11
- *
12
- * The sweep does not affect observable store semantics: expired entries are
13
- * already invisible to get()/has()/size() before the sweep runs.
6
+ * Disabled by default. The store evicts lazily on `get()` / `has()` access,
7
+ * which is sufficient for most use cases. Enable `autoCleanup` when the
8
+ * store is long-lived and accumulates many TTL'd entries that are never
9
+ * re-read — for example, a server-side cache that receives write-heavy
10
+ * traffic with low subsequent read rates.
14
11
  */
15
12
  autoCleanup?: boolean;
16
13
  /**
17
14
  * Interval between background sweeps in milliseconds.
18
- * Defaults to 30 000 (30 seconds). Ignored when autoCleanup is false.
19
- *
20
- * Choose a value appropriate to your TTL distribution — sweeping more often
21
- * than your shortest TTL is wasteful; sweeping much less often than your
22
- * longest TTL wastes memory.
15
+ * Defaults to 30 000 (30 seconds). Ignored when `autoCleanup` is false.
23
16
  */
24
17
  cleanupIntervalMs?: number;
18
+ /**
19
+ * Maximum number of live entries the store will hold.
20
+ *
21
+ * When `set()` would exceed this limit, the least-recently-used entry is
22
+ * evicted before the new one is inserted (LRU semantics). Updates to an
23
+ * existing key do not trigger eviction.
24
+ *
25
+ * Defaults to `Infinity` (unbounded). Set a finite value for long-running
26
+ * caches with high-cardinality keys to bound memory usage.
27
+ *
28
+ * The LRU order is updated on `get()` and `set()` — both move the accessed
29
+ * key to the most-recent position.
30
+ */
31
+ maxSize?: number;
25
32
  }
33
+ /**
34
+ * Reference `SyncStateStore` implementation backed by a `Map`.
35
+ *
36
+ * # LRU semantics
37
+ *
38
+ * `Map` iteration order is insertion order, so we implement LRU by
39
+ * `delete` + `set` on every access — the most-recently-touched key ends up
40
+ * at the end of the iteration, and the oldest is `entries.keys().next().value`.
41
+ *
42
+ * # Expiry
43
+ *
44
+ * Lazy on `get()` / `has()`: expired entries are deleted when touched.
45
+ * Background sweep (optional) reclaims entries that are never re-read.
46
+ */
26
47
  export declare class InMemoryStore implements SyncStateStore {
27
48
  readonly _sync: true;
28
49
  private readonly entries;
50
+ private readonly maxSize;
29
51
  private cleanupTimer;
30
52
  constructor(options?: InMemoryStoreOptions);
31
53
  get<T>(key: string): T | undefined;
32
54
  set<T>(key: string, value: T, ttlMs?: number): void;
33
55
  delete(key: string): void;
34
56
  has(key: string): boolean;
35
- /**
36
- * Remove all entries.
37
- * After this call, size() returns 0.
38
- */
39
57
  clear(): void;
40
58
  /**
41
59
  * Return the count of live (non-expired) entries.
42
60
  *
43
- * Expired entries are evicted during the scan, so repeated calls are
44
- * slightly cheaper as the map self-prunes. O(n) in the number of entries.
61
+ * Pure query does NOT touch LRU order. Expired entries discovered during
62
+ * the scan are evicted opportunistically (they were already invisible to
63
+ * `get()`, so eviction has no observable effect beyond memory reclamation).
64
+ *
65
+ * Two-pass to avoid mutating the Map during iteration (spec-safe).
45
66
  */
46
67
  size(): number;
47
68
  /**
48
69
  * Stop the background cleanup timer and release internal state.
49
70
  * Safe to call multiple times — subsequent calls are no-ops.
50
- *
51
- * Call destroy() when discarding a long-lived store instance to prevent
52
- * timer leaks. Stores without autoCleanup enabled have nothing to release,
53
- * but destroy() is safe to call on them regardless.
54
71
  */
55
72
  destroy(): void;
73
+ /**
74
+ * Sweep all entries and remove those past their expiry time.
75
+ * Called by the autoCleanup interval; not part of the public contract.
76
+ */
56
77
  private _sweep;
57
78
  }
58
79
  //# sourceMappingURL=memory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/stores/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAuB/C,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAID,qBAAa,aAAc,YAAW,cAAc;IAGlD,QAAQ,CAAC,KAAK,EAAG,IAAI,CAAS;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,YAAY,CAA4C;gBAEpD,OAAO,GAAE,oBAAyB;IAY9C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAYlC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAMnD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAKzB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAIb;;;;;OAKG;IACH,IAAI,IAAI,MAAM;IAOd;;;;;;;OAOG;IACH,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,MAAM;CAQf"}
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/stores/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAwB/C,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAE1B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAID;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,YAAW,cAAc;IAClD,QAAQ,CAAC,KAAK,EAAG,IAAI,CAAS;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,YAAY,CAA4C;gBAEpD,OAAO,GAAE,oBAAyB;IA0B9C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAiBlC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAcnD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAYzB,KAAK,IAAI,IAAI;IAIb;;;;;;;;OAQG;IACH,IAAI,IAAI,MAAM;IAiBd;;;OAGG;IACH,OAAO,IAAI,IAAI;IAOf;;;OAGG;IACH,OAAO,CAAC,MAAM;CAUf"}
@@ -2,17 +2,37 @@ function isUnrefable(t) {
2
2
  return typeof t.unref === 'function';
3
3
  }
4
4
  // ─── Implementation ───────────────────────────────────────────────────────────
5
+ /**
6
+ * Reference `SyncStateStore` implementation backed by a `Map`.
7
+ *
8
+ * # LRU semantics
9
+ *
10
+ * `Map` iteration order is insertion order, so we implement LRU by
11
+ * `delete` + `set` on every access — the most-recently-touched key ends up
12
+ * at the end of the iteration, and the oldest is `entries.keys().next().value`.
13
+ *
14
+ * # Expiry
15
+ *
16
+ * Lazy on `get()` / `has()`: expired entries are deleted when touched.
17
+ * Background sweep (optional) reclaims entries that are never re-read.
18
+ */
5
19
  export class InMemoryStore {
20
+ _sync = true;
21
+ entries = new Map();
22
+ maxSize;
23
+ cleanupTimer;
6
24
  constructor(options = {}) {
7
- // Discriminant read by isSyncStore() in execute() to enforce the dedupe
8
- // constraint at runtime for JS callers who bypass TypeScript.
9
- this._sync = true;
10
- this.entries = new Map();
11
- const { autoCleanup = false, cleanupIntervalMs = 30000 } = options;
25
+ const { autoCleanup = false, cleanupIntervalMs = 30_000, maxSize = Number.POSITIVE_INFINITY, } = options;
26
+ if (!Number.isFinite(maxSize) || maxSize <= 0) {
27
+ // Infinity is allowed (unbounded); any other non-positive finite value
28
+ // is a programmer error.
29
+ if (maxSize !== Number.POSITIVE_INFINITY) {
30
+ throw new RangeError(`Actly: InMemoryStore maxSize must be a positive finite number or Infinity, got ${maxSize}`);
31
+ }
32
+ }
33
+ this.maxSize = maxSize;
12
34
  if (autoCleanup) {
13
35
  const timer = setInterval(() => this._sweep(), cleanupIntervalMs);
14
- // Prevent the interval from keeping the Node.js process alive when the
15
- // application has otherwise finished its work. Safe no-op in browsers.
16
36
  if (isUnrefable(timer))
17
37
  timer.unref();
18
38
  this.cleanupTimer = timer;
@@ -26,47 +46,71 @@ export class InMemoryStore {
26
46
  this.entries.delete(key);
27
47
  return undefined;
28
48
  }
49
+ // LRU refresh: move to most-recent position.
50
+ // delete + set is the canonical pattern for reordering a Map.
51
+ this.entries.delete(key);
52
+ this.entries.set(key, entry);
29
53
  return entry.value;
30
54
  }
31
55
  set(key, value, ttlMs) {
32
- // ttlMs = 0 or undefined no expiry (sentinel null)
56
+ // Evict if at capacity AND adding a new key (updates don't grow size).
57
+ if (!this.entries.has(key) && this.entries.size >= this.maxSize) {
58
+ const oldest = this.entries.keys().next().value;
59
+ if (oldest !== undefined)
60
+ this.entries.delete(oldest);
61
+ }
33
62
  const expiresAt = ttlMs != null && ttlMs > 0 ? Date.now() + ttlMs : null;
63
+ // delete + set ensures the key is moved to the most-recent position
64
+ // even on update, keeping LRU order consistent.
65
+ this.entries.delete(key);
34
66
  this.entries.set(key, { value, expiresAt });
35
67
  }
36
68
  delete(key) {
37
69
  this.entries.delete(key);
38
70
  }
39
71
  has(key) {
40
- // Delegate to get() so expired entries are evicted on access.
41
- return this.get(key) !== undefined;
72
+ // Inline the expiry check to avoid the LRU side-effect of get().
73
+ // `has()` should be a pure query, not a touch.
74
+ const entry = this.entries.get(key);
75
+ if (!entry)
76
+ return false;
77
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
78
+ this.entries.delete(key);
79
+ return false;
80
+ }
81
+ return true;
42
82
  }
43
- /**
44
- * Remove all entries.
45
- * After this call, size() returns 0.
46
- */
47
83
  clear() {
48
84
  this.entries.clear();
49
85
  }
50
86
  /**
51
87
  * Return the count of live (non-expired) entries.
52
88
  *
53
- * Expired entries are evicted during the scan, so repeated calls are
54
- * slightly cheaper as the map self-prunes. O(n) in the number of entries.
89
+ * Pure query does NOT touch LRU order. Expired entries discovered during
90
+ * the scan are evicted opportunistically (they were already invisible to
91
+ * `get()`, so eviction has no observable effect beyond memory reclamation).
92
+ *
93
+ * Two-pass to avoid mutating the Map during iteration (spec-safe).
55
94
  */
56
95
  size() {
57
- // Evict expired entries as we scan — keeps the map tidy between sweeps
58
- // and ensures the returned count reflects only observable entries.
59
- for (const key of this.entries.keys())
60
- this.has(key);
61
- return this.entries.size;
96
+ const now = Date.now();
97
+ const expired = [];
98
+ let count = 0;
99
+ for (const [key, entry] of this.entries) {
100
+ if (entry.expiresAt !== null && entry.expiresAt <= now) {
101
+ expired.push(key);
102
+ }
103
+ else {
104
+ count++;
105
+ }
106
+ }
107
+ for (const key of expired)
108
+ this.entries.delete(key);
109
+ return count;
62
110
  }
63
111
  /**
64
112
  * Stop the background cleanup timer and release internal state.
65
113
  * Safe to call multiple times — subsequent calls are no-ops.
66
- *
67
- * Call destroy() when discarding a long-lived store instance to prevent
68
- * timer leaks. Stores without autoCleanup enabled have nothing to release,
69
- * but destroy() is safe to call on them regardless.
70
114
  */
71
115
  destroy() {
72
116
  if (this.cleanupTimer !== undefined) {
@@ -74,15 +118,20 @@ export class InMemoryStore {
74
118
  this.cleanupTimer = undefined;
75
119
  }
76
120
  }
77
- // Sweep all entries and remove those past their expiry time.
78
- // Called by the autoCleanup interval not part of the public contract.
121
+ /**
122
+ * Sweep all entries and remove those past their expiry time.
123
+ * Called by the autoCleanup interval; not part of the public contract.
124
+ */
79
125
  _sweep() {
80
126
  const now = Date.now();
127
+ const expired = [];
81
128
  for (const [key, entry] of this.entries) {
82
129
  if (entry.expiresAt !== null && now > entry.expiresAt) {
83
- this.entries.delete(key);
130
+ expired.push(key);
84
131
  }
85
132
  }
133
+ for (const key of expired)
134
+ this.entries.delete(key);
86
135
  }
87
136
  }
88
137
  //# sourceMappingURL=memory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/stores/memory.ts"],"names":[],"mappings":"AAiBA,SAAS,WAAW,CAAC,CAAU;IAC7B,OAAO,OAAQ,CAAoB,CAAC,KAAK,KAAK,UAAU,CAAA;AAC1D,CAAC;AA8BD,iFAAiF;AAEjF,MAAM,OAAO,aAAa;IAQxB,YAAY,UAAgC,EAAE;QAP9C,wEAAwE;QACxE,8DAA8D;QACrD,UAAK,GAAG,IAAa,CAAA;QAEb,YAAO,GAAG,IAAI,GAAG,EAA0B,CAAA;QAI1D,MAAM,EAAE,WAAW,GAAG,KAAK,EAAE,iBAAiB,GAAG,KAAM,EAAE,GAAG,OAAO,CAAA;QAEnE,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAA;YACjE,uEAAuE;YACvE,uEAAuE;YACvE,IAAI,WAAW,CAAC,KAAK,CAAC;gBAAE,KAAK,CAAC,KAAK,EAAE,CAAA;YACrC,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QAC3B,CAAC;IACH,CAAC;IAED,GAAG,CAAI,GAAW;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAA;QAE5B,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YAC7D,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACxB,OAAO,SAAS,CAAA;QAClB,CAAC;QAED,OAAO,KAAK,CAAC,KAAU,CAAA;IACzB,CAAC;IAED,GAAG,CAAI,GAAW,EAAE,KAAQ,EAAE,KAAc;QAC1C,qDAAqD;QACrD,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;QACxE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;IAC7C,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAED,GAAG,CAAC,GAAW;QACb,8DAA8D;QAC9D,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,CAAA;IACpC,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC;IAED;;;;;OAKG;IACH,IAAI;QACF,uEAAuE;QACvE,mEAAmE;QACnE,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACpD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAA;IAC1B,CAAC;IAED;;;;;;;OAOG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACpC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;YAChC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAA;QAC/B,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,wEAAwE;IAChE,MAAM;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACxC,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;gBACtD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/stores/memory.ts"],"names":[],"mappings":"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"}