@http-client-toolkit/store-memory 0.0.1 → 0.3.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.
package/lib/index.cjs CHANGED
@@ -4,9 +4,11 @@ var safeStringify = require('fast-safe-stringify');
4
4
  var crypto = require('crypto');
5
5
  var core = require('@http-client-toolkit/core');
6
6
 
7
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+ function _interopDefault(e) {
8
+ return e && e.__esModule ? e : { default: e };
9
+ }
8
10
 
9
- var safeStringify__default = /*#__PURE__*/_interopDefault(safeStringify);
11
+ var safeStringify__default = /*#__PURE__*/ _interopDefault(safeStringify);
10
12
 
11
13
  var __async = (__this, __arguments, generator) => {
12
14
  return new Promise((resolve, reject) => {
@@ -24,7 +26,10 @@ var __async = (__this, __arguments, generator) => {
24
26
  reject(e);
25
27
  }
26
28
  };
27
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
29
+ var step = (x) =>
30
+ x.done
31
+ ? resolve(x.value)
32
+ : Promise.resolve(x.value).then(fulfilled, rejected);
28
33
  step((generator = generator.apply(__this, __arguments)).next());
29
34
  });
30
35
  };
@@ -34,15 +39,17 @@ var InMemoryCacheStore = class {
34
39
  this.cache = /* @__PURE__ */ new Map();
35
40
  this.totalSize = 0;
36
41
  var _a, _b, _c, _d;
37
- const cleanupIntervalMs = (_a = options.cleanupIntervalMs) != null ? _a : 6e4;
42
+ const cleanupIntervalMs =
43
+ (_a = options.cleanupIntervalMs) != null ? _a : 6e4;
38
44
  this.maxItems = (_b = options.maxItems) != null ? _b : 1e3;
39
- this.maxMemoryBytes = (_c = options.maxMemoryBytes) != null ? _c : 50 * 1024 * 1024;
45
+ this.maxMemoryBytes =
46
+ (_c = options.maxMemoryBytes) != null ? _c : 50 * 1024 * 1024;
40
47
  this.evictionRatio = (_d = options.evictionRatio) != null ? _d : 0.1;
41
48
  if (cleanupIntervalMs > 0) {
42
49
  this.cleanupInterval = setInterval(() => {
43
50
  this.cleanup();
44
51
  }, cleanupIntervalMs);
45
- if (typeof this.cleanupInterval.unref === "function") {
52
+ if (typeof this.cleanupInterval.unref === 'function') {
46
53
  this.cleanupInterval.unref();
47
54
  }
48
55
  }
@@ -77,7 +84,7 @@ var InMemoryCacheStore = class {
77
84
  value,
78
85
  expiresAt,
79
86
  lastAccessed: now,
80
- size: entrySize
87
+ size: entrySize,
81
88
  });
82
89
  this.enforceMemoryLimits();
83
90
  });
@@ -116,7 +123,7 @@ var InMemoryCacheStore = class {
116
123
  maxItems: this.maxItems,
117
124
  maxMemoryBytes: this.maxMemoryBytes,
118
125
  memoryUtilization: memoryUsageBytes / this.maxMemoryBytes,
119
- itemUtilization: this.cache.size / this.maxItems
126
+ itemUtilization: this.cache.size / this.maxItems,
120
127
  };
121
128
  }
122
129
  /**
@@ -150,7 +157,7 @@ var InMemoryCacheStore = class {
150
157
  if (memoryUsage > this.maxMemoryBytes) {
151
158
  const itemsToEvict = Math.max(
152
159
  1,
153
- Math.floor(this.cache.size * this.evictionRatio)
160
+ Math.floor(this.cache.size * this.evictionRatio),
154
161
  );
155
162
  this.evictLRUItems(itemsToEvict);
156
163
  }
@@ -160,7 +167,7 @@ var InMemoryCacheStore = class {
160
167
  */
161
168
  evictLRUItems(count) {
162
169
  const entries = Array.from(this.cache.entries()).sort(
163
- ([, a], [, b]) => a.lastAccessed - b.lastAccessed
170
+ ([, a], [, b]) => a.lastAccessed - b.lastAccessed,
164
171
  );
165
172
  for (let i = 0; i < count && i < entries.length; i++) {
166
173
  const entry = entries[i];
@@ -181,11 +188,13 @@ var InMemoryCacheStore = class {
181
188
  * Get items sorted by last accessed time (for debugging/monitoring)
182
189
  */
183
190
  getLRUItems(limit = 10) {
184
- const entries = Array.from(this.cache.entries()).sort(([, a], [, b]) => a.lastAccessed - b.lastAccessed).slice(0, limit);
191
+ const entries = Array.from(this.cache.entries())
192
+ .sort(([, a], [, b]) => a.lastAccessed - b.lastAccessed)
193
+ .slice(0, limit);
185
194
  return entries.map(([hash, item]) => ({
186
195
  hash,
187
196
  lastAccessed: new Date(item.lastAccessed),
188
- size: item.size
197
+ size: item.size,
189
198
  }));
190
199
  }
191
200
  /**
@@ -208,7 +217,8 @@ var InMemoryCacheStore = class {
208
217
  size += hash.length * 2;
209
218
  size += 16;
210
219
  try {
211
- const json = (_a = safeStringify__default.default(value)) != null ? _a : "";
220
+ const json =
221
+ (_a = safeStringify__default.default(value)) != null ? _a : '';
212
222
  size += json.length * 2;
213
223
  } catch (e) {
214
224
  size += 1024;
@@ -230,7 +240,7 @@ var InMemoryDedupeStore = class {
230
240
  /** Job timeout in milliseconds. Defaults to 5 minutes. */
231
241
  jobTimeoutMs = 3e5,
232
242
  /** Cleanup interval in milliseconds. Defaults to 1 minute. */
233
- cleanupIntervalMs = 6e4
243
+ cleanupIntervalMs = 6e4,
234
244
  } = {}) {
235
245
  this.jobs = /* @__PURE__ */ new Map();
236
246
  this.totalJobsProcessed = 0;
@@ -240,7 +250,7 @@ var InMemoryDedupeStore = class {
240
250
  this.cleanupInterval = setInterval(() => {
241
251
  this.cleanup();
242
252
  }, cleanupIntervalMs);
243
- if (typeof this.cleanupInterval.unref === "function") {
253
+ if (typeof this.cleanupInterval.unref === 'function') {
244
254
  this.cleanupInterval.unref();
245
255
  }
246
256
  }
@@ -255,7 +265,8 @@ var InMemoryDedupeStore = class {
255
265
  if (!job) {
256
266
  return void 0;
257
267
  }
258
- const jobTimedOut = this.jobTimeoutMs > 0 && Date.now() - job.createdAt > this.jobTimeoutMs;
268
+ const jobTimedOut =
269
+ this.jobTimeoutMs > 0 && Date.now() - job.createdAt > this.jobTimeoutMs;
259
270
  if (jobTimedOut) {
260
271
  this.cleanup();
261
272
  return void 0;
@@ -285,7 +296,7 @@ var InMemoryDedupeStore = class {
285
296
  if (existingJob) {
286
297
  return {
287
298
  jobId: existingJob.jobId,
288
- isOwner: false
299
+ isOwner: false,
289
300
  };
290
301
  }
291
302
  const jobId = crypto.randomUUID();
@@ -296,13 +307,13 @@ var InMemoryDedupeStore = class {
296
307
  resolve,
297
308
  reject,
298
309
  createdAt: Date.now(),
299
- completed: false
310
+ completed: false,
300
311
  };
301
312
  this.jobs.set(hash, job);
302
313
  this.totalJobsProcessed++;
303
314
  return {
304
315
  jobId,
305
- isOwner: true
316
+ isOwner: true,
306
317
  };
307
318
  });
308
319
  }
@@ -332,7 +343,8 @@ var InMemoryDedupeStore = class {
332
343
  if (!job) {
333
344
  return false;
334
345
  }
335
- const isJobExpired = this.jobTimeoutMs > 0 && Date.now() - job.createdAt > this.jobTimeoutMs;
346
+ const isJobExpired =
347
+ this.jobTimeoutMs > 0 && Date.now() - job.createdAt > this.jobTimeoutMs;
336
348
  if (isJobExpired) {
337
349
  this.cleanup();
338
350
  return false;
@@ -364,7 +376,7 @@ var InMemoryDedupeStore = class {
364
376
  activeJobs,
365
377
  totalJobsProcessed: this.totalJobsProcessed,
366
378
  expiredJobs,
367
- oldestJobAgeMs
379
+ oldestJobAgeMs,
368
380
  };
369
381
  }
370
382
  /**
@@ -381,7 +393,7 @@ var InMemoryDedupeStore = class {
381
393
  if (!job.completed) {
382
394
  job.completed = true;
383
395
  job.error = new Error(
384
- "Job timeout: Request took too long to complete"
396
+ 'Job timeout: Request took too long to complete',
385
397
  );
386
398
  job.reject(job.error);
387
399
  }
@@ -399,7 +411,7 @@ var InMemoryDedupeStore = class {
399
411
  for (const [_hash, job] of this.jobs) {
400
412
  if (!job.completed) {
401
413
  job.completed = true;
402
- job.error = new Error("DedupeStore cleared");
414
+ job.error = new Error('DedupeStore cleared');
403
415
  job.reject(job.error);
404
416
  }
405
417
  }
@@ -424,7 +436,7 @@ var InMemoryRateLimitStore = class {
424
436
  /** Optional per-resource overrides. */
425
437
  resourceConfigs = /* @__PURE__ */ new Map(),
426
438
  /** Cleanup interval in milliseconds. Defaults to 1 minute. */
427
- cleanupIntervalMs = 6e4
439
+ cleanupIntervalMs = 6e4,
428
440
  } = {}) {
429
441
  this.limits = /* @__PURE__ */ new Map();
430
442
  this.resourceConfigs = /* @__PURE__ */ new Map();
@@ -435,7 +447,7 @@ var InMemoryRateLimitStore = class {
435
447
  this.cleanupInterval = setInterval(() => {
436
448
  this.cleanup();
437
449
  }, cleanupIntervalMs);
438
- if (typeof this.cleanupInterval.unref === "function") {
450
+ if (typeof this.cleanupInterval.unref === 'function') {
439
451
  this.cleanupInterval.unref();
440
452
  }
441
453
  }
@@ -467,7 +479,7 @@ var InMemoryRateLimitStore = class {
467
479
  return {
468
480
  remaining: Math.max(0, info.limit - info.requests.length),
469
481
  resetTime: new Date(info.resetTime),
470
- limit: info.limit
482
+ limit: info.limit,
471
483
  };
472
484
  });
473
485
  }
@@ -477,7 +489,7 @@ var InMemoryRateLimitStore = class {
477
489
  if (info) {
478
490
  this.totalRequests = Math.max(
479
491
  0,
480
- this.totalRequests - info.requests.length
492
+ this.totalRequests - info.requests.length,
481
493
  );
482
494
  }
483
495
  this.limits.delete(resource);
@@ -498,7 +510,8 @@ var InMemoryRateLimitStore = class {
498
510
  if (oldestRequest === void 0) {
499
511
  return 0;
500
512
  }
501
- const timeUntilOldestExpires = oldestRequest + config.windowMs - Date.now();
513
+ const timeUntilOldestExpires =
514
+ oldestRequest + config.windowMs - Date.now();
502
515
  return Math.max(0, timeUntilOldestExpires);
503
516
  });
504
517
  }
@@ -534,7 +547,7 @@ var InMemoryRateLimitStore = class {
534
547
  totalResources: this.limits.size,
535
548
  activeResources,
536
549
  rateLimitedResources,
537
- totalRequests: this.totalRequests
550
+ totalRequests: this.totalRequests,
538
551
  };
539
552
  }
540
553
  /**
@@ -569,7 +582,7 @@ var InMemoryRateLimitStore = class {
569
582
  requests: [],
570
583
  limit: config.limit,
571
584
  windowMs: config.windowMs,
572
- resetTime: Date.now() + config.windowMs
585
+ resetTime: Date.now() + config.windowMs,
573
586
  };
574
587
  this.limits.set(resource, info);
575
588
  }
@@ -595,48 +608,51 @@ var AdaptiveRateLimitStore = class {
595
608
  this.lastCapacityUpdate = /* @__PURE__ */ new Map();
596
609
  this.cachedCapacity = /* @__PURE__ */ new Map();
597
610
  var _a, _b;
598
- this.defaultConfig = (_a = options.defaultConfig) != null ? _a : core.DEFAULT_RATE_LIMIT;
599
- this.resourceConfigs = (_b = options.resourceConfigs) != null ? _b : /* @__PURE__ */ new Map();
611
+ this.defaultConfig =
612
+ (_a = options.defaultConfig) != null ? _a : core.DEFAULT_RATE_LIMIT;
613
+ this.resourceConfigs =
614
+ (_b = options.resourceConfigs) != null ? _b : /* @__PURE__ */ new Map();
600
615
  this.capacityCalculator = new core.AdaptiveCapacityCalculator(
601
- options.adaptiveConfig
616
+ options.adaptiveConfig,
602
617
  );
603
618
  }
604
- canProceed(resource, priority = "background") {
619
+ canProceed(resource, priority = 'background') {
605
620
  return __async(this, null, function* () {
606
621
  const metrics = this.getOrCreateActivityMetrics(resource);
607
622
  const capacity = this.calculateCurrentCapacity(resource, metrics);
608
- if (priority === "background" && capacity.backgroundPaused) {
623
+ if (priority === 'background' && capacity.backgroundPaused) {
609
624
  return false;
610
625
  }
611
626
  const currentUserRequests = this.getCurrentUsage(
612
627
  resource,
613
- metrics.recentUserRequests
628
+ metrics.recentUserRequests,
614
629
  );
615
630
  const currentBackgroundRequests = this.getCurrentUsage(
616
631
  resource,
617
- metrics.recentBackgroundRequests
632
+ metrics.recentBackgroundRequests,
618
633
  );
619
- if (priority === "user") {
634
+ if (priority === 'user') {
620
635
  return currentUserRequests < capacity.userReserved;
621
636
  } else {
622
637
  return currentBackgroundRequests < capacity.backgroundMax;
623
638
  }
624
639
  });
625
640
  }
626
- record(resource, priority = "background") {
641
+ record(resource, priority = 'background') {
627
642
  return __async(this, null, function* () {
628
643
  const metrics = this.getOrCreateActivityMetrics(resource);
629
644
  const now = Date.now();
630
- if (priority === "user") {
645
+ if (priority === 'user') {
631
646
  metrics.recentUserRequests.push(now);
632
647
  this.cleanupOldRequests(metrics.recentUserRequests);
633
648
  } else {
634
649
  metrics.recentBackgroundRequests.push(now);
635
650
  this.cleanupOldRequests(metrics.recentBackgroundRequests);
636
651
  }
637
- metrics.userActivityTrend = this.capacityCalculator.calculateActivityTrend(
638
- metrics.recentUserRequests
639
- );
652
+ metrics.userActivityTrend =
653
+ this.capacityCalculator.calculateActivityTrend(
654
+ metrics.recentUserRequests,
655
+ );
640
656
  });
641
657
  }
642
658
  getStatus(resource) {
@@ -646,15 +662,21 @@ var AdaptiveRateLimitStore = class {
646
662
  const capacity = this.calculateCurrentCapacity(resource, metrics);
647
663
  const currentUserUsage = this.getCurrentUsage(
648
664
  resource,
649
- metrics.recentUserRequests
665
+ metrics.recentUserRequests,
650
666
  );
651
667
  const currentBackgroundUsage = this.getCurrentUsage(
652
668
  resource,
653
- metrics.recentBackgroundRequests
669
+ metrics.recentBackgroundRequests,
654
670
  );
655
- const config = (_a = this.resourceConfigs.get(resource)) != null ? _a : this.defaultConfig;
671
+ const config =
672
+ (_a = this.resourceConfigs.get(resource)) != null
673
+ ? _a
674
+ : this.defaultConfig;
656
675
  return {
657
- remaining: capacity.userReserved - currentUserUsage + (capacity.backgroundMax - currentBackgroundUsage),
676
+ remaining:
677
+ capacity.userReserved -
678
+ currentUserUsage +
679
+ (capacity.backgroundMax - currentBackgroundUsage),
658
680
  resetTime: new Date(Date.now() + config.windowMs),
659
681
  limit: this.getResourceLimit(resource),
660
682
  adaptive: {
@@ -662,10 +684,10 @@ var AdaptiveRateLimitStore = class {
662
684
  backgroundMax: capacity.backgroundMax,
663
685
  backgroundPaused: capacity.backgroundPaused,
664
686
  recentUserActivity: this.capacityCalculator.getRecentActivity(
665
- metrics.recentUserRequests
687
+ metrics.recentUserRequests,
666
688
  ),
667
- reason: capacity.reason
668
- }
689
+ reason: capacity.reason,
690
+ },
669
691
  };
670
692
  });
671
693
  }
@@ -676,7 +698,7 @@ var AdaptiveRateLimitStore = class {
676
698
  this.lastCapacityUpdate.delete(resource);
677
699
  });
678
700
  }
679
- getWaitTime(resource, priority = "background") {
701
+ getWaitTime(resource, priority = 'background') {
680
702
  return __async(this, null, function* () {
681
703
  const canProceed = yield this.canProceed(resource, priority);
682
704
  if (canProceed) {
@@ -684,13 +706,18 @@ var AdaptiveRateLimitStore = class {
684
706
  }
685
707
  const metrics = this.getOrCreateActivityMetrics(resource);
686
708
  const capacity = this.calculateCurrentCapacity(resource, metrics);
687
- if (priority === "background" && capacity.backgroundPaused) {
709
+ if (priority === 'background' && capacity.backgroundPaused) {
688
710
  const lastUpdate = this.lastCapacityUpdate.get(resource) || 0;
689
- const nextUpdate = lastUpdate + this.capacityCalculator.config.recalculationIntervalMs;
711
+ const nextUpdate =
712
+ lastUpdate + this.capacityCalculator.config.recalculationIntervalMs;
690
713
  return Math.max(0, nextUpdate - Date.now());
691
714
  }
692
- const monitoringWindow = this.capacityCalculator.config.monitoringWindowMs;
693
- const requests = priority === "user" ? metrics.recentUserRequests : metrics.recentBackgroundRequests;
715
+ const monitoringWindow =
716
+ this.capacityCalculator.config.monitoringWindowMs;
717
+ const requests =
718
+ priority === 'user'
719
+ ? metrics.recentUserRequests
720
+ : metrics.recentBackgroundRequests;
694
721
  if (requests.length === 0) {
695
722
  return 0;
696
723
  }
@@ -701,15 +728,18 @@ var AdaptiveRateLimitStore = class {
701
728
  }
702
729
  calculateCurrentCapacity(resource, metrics) {
703
730
  const lastUpdate = this.lastCapacityUpdate.get(resource) || 0;
704
- const recalcInterval = this.capacityCalculator.config.recalculationIntervalMs;
731
+ const recalcInterval =
732
+ this.capacityCalculator.config.recalculationIntervalMs;
705
733
  if (Date.now() - lastUpdate < recalcInterval) {
706
- return this.cachedCapacity.get(resource) || this.getDefaultCapacity(resource);
734
+ return (
735
+ this.cachedCapacity.get(resource) || this.getDefaultCapacity(resource)
736
+ );
707
737
  }
708
738
  const totalLimit = this.getResourceLimit(resource);
709
739
  const capacity = this.capacityCalculator.calculateDynamicCapacity(
710
740
  resource,
711
741
  totalLimit,
712
- metrics
742
+ metrics,
713
743
  );
714
744
  this.cachedCapacity.set(resource, capacity);
715
745
  this.lastCapacityUpdate.set(resource, Date.now());
@@ -720,26 +750,33 @@ var AdaptiveRateLimitStore = class {
720
750
  this.activityMetrics.set(resource, {
721
751
  recentUserRequests: [],
722
752
  recentBackgroundRequests: [],
723
- userActivityTrend: "none"
753
+ userActivityTrend: 'none',
724
754
  });
725
755
  }
726
756
  return this.activityMetrics.get(resource);
727
757
  }
728
758
  getCurrentUsage(resource, requests) {
729
759
  var _a;
730
- const config = (_a = this.resourceConfigs.get(resource)) != null ? _a : this.defaultConfig;
760
+ const config =
761
+ (_a = this.resourceConfigs.get(resource)) != null
762
+ ? _a
763
+ : this.defaultConfig;
731
764
  const windowStart = Date.now() - config.windowMs;
732
765
  return requests.filter((timestamp) => timestamp > windowStart).length;
733
766
  }
734
767
  cleanupOldRequests(requests) {
735
- const cutoff = Date.now() - this.capacityCalculator.config.monitoringWindowMs;
768
+ const cutoff =
769
+ Date.now() - this.capacityCalculator.config.monitoringWindowMs;
736
770
  while (requests.length > 0 && requests[0] < cutoff) {
737
771
  requests.shift();
738
772
  }
739
773
  }
740
774
  getResourceLimit(resource) {
741
775
  var _a;
742
- const config = (_a = this.resourceConfigs.get(resource)) != null ? _a : this.defaultConfig;
776
+ const config =
777
+ (_a = this.resourceConfigs.get(resource)) != null
778
+ ? _a
779
+ : this.defaultConfig;
743
780
  return config.limit;
744
781
  }
745
782
  getDefaultCapacity(resource) {
@@ -748,7 +785,7 @@ var AdaptiveRateLimitStore = class {
748
785
  userReserved: Math.floor(totalLimit * 0.3),
749
786
  backgroundMax: Math.floor(totalLimit * 0.7),
750
787
  backgroundPaused: false,
751
- reason: "Default capacity allocation"
788
+ reason: 'Default capacity allocation',
752
789
  };
753
790
  }
754
791
  };
@@ -758,4 +795,4 @@ exports.InMemoryCacheStore = InMemoryCacheStore;
758
795
  exports.InMemoryDedupeStore = InMemoryDedupeStore;
759
796
  exports.InMemoryRateLimitStore = InMemoryRateLimitStore;
760
797
  //# sourceMappingURL=index.cjs.map
761
- //# sourceMappingURL=index.cjs.map
798
+ //# sourceMappingURL=index.cjs.map