@adaptic/utils 0.0.1008 → 0.0.1009
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 +35 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +35 -0
- package/dist/index.mjs.map +1 -1
- package/dist/types/cache/stampede-protected-cache.d.ts +28 -0
- package/dist/types/cache/stampede-protected-cache.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -63618,6 +63618,15 @@ class StampedeProtectedCache {
|
|
|
63618
63618
|
allowStale: true,
|
|
63619
63619
|
updateAgeOnGet: false,
|
|
63620
63620
|
updateAgeOnHas: false,
|
|
63621
|
+
// LRU discard visibility for the onEvent observability hook. lru-cache
|
|
63622
|
+
// invokes dispose for every removal; only capacity discards ("evict")
|
|
63623
|
+
// are reported as evictions so deliberate delete()/invalidate() calls
|
|
63624
|
+
// do not inflate the eviction signal.
|
|
63625
|
+
dispose: (_value, key, reason) => {
|
|
63626
|
+
if (reason === "evict") {
|
|
63627
|
+
this.emitEvent("eviction", key);
|
|
63628
|
+
}
|
|
63629
|
+
},
|
|
63621
63630
|
});
|
|
63622
63631
|
this.options.logger.info("StampedeProtectedCache initialized", {
|
|
63623
63632
|
maxSize: this.options.maxSize,
|
|
@@ -63685,6 +63694,7 @@ class StampedeProtectedCache {
|
|
|
63685
63694
|
if (now < jitteredExpiresAt) {
|
|
63686
63695
|
// Fresh hit
|
|
63687
63696
|
this.stats.hits++;
|
|
63697
|
+
this.emitEvent("hit", key);
|
|
63688
63698
|
this.options.logger.debug("Cache hit (fresh)", {
|
|
63689
63699
|
key,
|
|
63690
63700
|
age: now - cached.createdAt,
|
|
@@ -63696,6 +63706,7 @@ class StampedeProtectedCache {
|
|
|
63696
63706
|
if (now < staleExpiresAt && !cached.isRefreshing) {
|
|
63697
63707
|
// Serve stale and trigger background refresh
|
|
63698
63708
|
this.stats.staleHits++;
|
|
63709
|
+
this.emitEvent("stale_hit", key);
|
|
63699
63710
|
this.options.logger.debug("Cache hit (stale-while-revalidate)", {
|
|
63700
63711
|
key,
|
|
63701
63712
|
age: now - cached.createdAt,
|
|
@@ -63709,6 +63720,7 @@ class StampedeProtectedCache {
|
|
|
63709
63720
|
}
|
|
63710
63721
|
// Cache miss or expired - need to load
|
|
63711
63722
|
this.stats.misses++;
|
|
63723
|
+
this.emitEvent("miss", key);
|
|
63712
63724
|
this.options.logger.debug("Cache miss", { key, hadCached: !!cached });
|
|
63713
63725
|
return this.loadWithCoalescing(key, loader, effectiveTtl);
|
|
63714
63726
|
}
|
|
@@ -63786,6 +63798,25 @@ class StampedeProtectedCache {
|
|
|
63786
63798
|
* cache.delete(`positions:${accountId}`);
|
|
63787
63799
|
* ```
|
|
63788
63800
|
*/
|
|
63801
|
+
/**
|
|
63802
|
+
* Fire the {@link StampedeProtectedCacheOptions.onEvent} hook, never
|
|
63803
|
+
* letting an observer failure propagate into the cache path.
|
|
63804
|
+
*/
|
|
63805
|
+
emitEvent(event, key) {
|
|
63806
|
+
const hook = this.options.onEvent;
|
|
63807
|
+
if (!hook)
|
|
63808
|
+
return;
|
|
63809
|
+
try {
|
|
63810
|
+
hook(event, key);
|
|
63811
|
+
}
|
|
63812
|
+
catch (err) {
|
|
63813
|
+
this.options.logger.warn("cache onEvent observer threw — ignored", {
|
|
63814
|
+
event,
|
|
63815
|
+
key,
|
|
63816
|
+
error: err instanceof Error ? err.message : String(err),
|
|
63817
|
+
});
|
|
63818
|
+
}
|
|
63819
|
+
}
|
|
63789
63820
|
delete(key) {
|
|
63790
63821
|
const deleted = this.cache.delete(key);
|
|
63791
63822
|
if (deleted) {
|
|
@@ -63918,6 +63949,7 @@ class StampedeProtectedCache {
|
|
|
63918
63949
|
const existingPromise = this.pendingRefreshes.get(key);
|
|
63919
63950
|
if (existingPromise) {
|
|
63920
63951
|
this.stats.coalescedRequests++;
|
|
63952
|
+
this.emitEvent("coalesced", key);
|
|
63921
63953
|
this.options.logger.debug("Request coalesced", { key });
|
|
63922
63954
|
return existingPromise;
|
|
63923
63955
|
}
|
|
@@ -63951,6 +63983,7 @@ class StampedeProtectedCache {
|
|
|
63951
63983
|
const timeoutPromise = new Promise((_, reject) => {
|
|
63952
63984
|
timeoutHandle = setTimeout(() => {
|
|
63953
63985
|
this.stats.loadTimeouts++;
|
|
63986
|
+
this.emitEvent("load_timeout", key);
|
|
63954
63987
|
// Mark the invocation abandoned BEFORE evicting the pin: a retry that
|
|
63955
63988
|
// starts now must never be overwritten by this loader's late result.
|
|
63956
63989
|
invocation.abandoned = true;
|
|
@@ -64007,6 +64040,7 @@ class StampedeProtectedCache {
|
|
|
64007
64040
|
}
|
|
64008
64041
|
catch (error) {
|
|
64009
64042
|
this.stats.refreshErrors++;
|
|
64043
|
+
this.emitEvent("refresh_error", key);
|
|
64010
64044
|
const loadTime = Date.now() - startTime;
|
|
64011
64045
|
this.options.logger.error("Failed to load data", {
|
|
64012
64046
|
key,
|
|
@@ -64039,6 +64073,7 @@ class StampedeProtectedCache {
|
|
|
64039
64073
|
this.loadWithCoalescing(key, loader, ttl)
|
|
64040
64074
|
.then(() => {
|
|
64041
64075
|
this.stats.backgroundRefreshes++;
|
|
64076
|
+
this.emitEvent("background_refresh", key);
|
|
64042
64077
|
this.options.logger.debug("Background refresh completed", { key });
|
|
64043
64078
|
})
|
|
64044
64079
|
.catch((error) => {
|