@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.mjs
CHANGED
|
@@ -63616,6 +63616,15 @@ class StampedeProtectedCache {
|
|
|
63616
63616
|
allowStale: true,
|
|
63617
63617
|
updateAgeOnGet: false,
|
|
63618
63618
|
updateAgeOnHas: false,
|
|
63619
|
+
// LRU discard visibility for the onEvent observability hook. lru-cache
|
|
63620
|
+
// invokes dispose for every removal; only capacity discards ("evict")
|
|
63621
|
+
// are reported as evictions so deliberate delete()/invalidate() calls
|
|
63622
|
+
// do not inflate the eviction signal.
|
|
63623
|
+
dispose: (_value, key, reason) => {
|
|
63624
|
+
if (reason === "evict") {
|
|
63625
|
+
this.emitEvent("eviction", key);
|
|
63626
|
+
}
|
|
63627
|
+
},
|
|
63619
63628
|
});
|
|
63620
63629
|
this.options.logger.info("StampedeProtectedCache initialized", {
|
|
63621
63630
|
maxSize: this.options.maxSize,
|
|
@@ -63683,6 +63692,7 @@ class StampedeProtectedCache {
|
|
|
63683
63692
|
if (now < jitteredExpiresAt) {
|
|
63684
63693
|
// Fresh hit
|
|
63685
63694
|
this.stats.hits++;
|
|
63695
|
+
this.emitEvent("hit", key);
|
|
63686
63696
|
this.options.logger.debug("Cache hit (fresh)", {
|
|
63687
63697
|
key,
|
|
63688
63698
|
age: now - cached.createdAt,
|
|
@@ -63694,6 +63704,7 @@ class StampedeProtectedCache {
|
|
|
63694
63704
|
if (now < staleExpiresAt && !cached.isRefreshing) {
|
|
63695
63705
|
// Serve stale and trigger background refresh
|
|
63696
63706
|
this.stats.staleHits++;
|
|
63707
|
+
this.emitEvent("stale_hit", key);
|
|
63697
63708
|
this.options.logger.debug("Cache hit (stale-while-revalidate)", {
|
|
63698
63709
|
key,
|
|
63699
63710
|
age: now - cached.createdAt,
|
|
@@ -63707,6 +63718,7 @@ class StampedeProtectedCache {
|
|
|
63707
63718
|
}
|
|
63708
63719
|
// Cache miss or expired - need to load
|
|
63709
63720
|
this.stats.misses++;
|
|
63721
|
+
this.emitEvent("miss", key);
|
|
63710
63722
|
this.options.logger.debug("Cache miss", { key, hadCached: !!cached });
|
|
63711
63723
|
return this.loadWithCoalescing(key, loader, effectiveTtl);
|
|
63712
63724
|
}
|
|
@@ -63784,6 +63796,25 @@ class StampedeProtectedCache {
|
|
|
63784
63796
|
* cache.delete(`positions:${accountId}`);
|
|
63785
63797
|
* ```
|
|
63786
63798
|
*/
|
|
63799
|
+
/**
|
|
63800
|
+
* Fire the {@link StampedeProtectedCacheOptions.onEvent} hook, never
|
|
63801
|
+
* letting an observer failure propagate into the cache path.
|
|
63802
|
+
*/
|
|
63803
|
+
emitEvent(event, key) {
|
|
63804
|
+
const hook = this.options.onEvent;
|
|
63805
|
+
if (!hook)
|
|
63806
|
+
return;
|
|
63807
|
+
try {
|
|
63808
|
+
hook(event, key);
|
|
63809
|
+
}
|
|
63810
|
+
catch (err) {
|
|
63811
|
+
this.options.logger.warn("cache onEvent observer threw — ignored", {
|
|
63812
|
+
event,
|
|
63813
|
+
key,
|
|
63814
|
+
error: err instanceof Error ? err.message : String(err),
|
|
63815
|
+
});
|
|
63816
|
+
}
|
|
63817
|
+
}
|
|
63787
63818
|
delete(key) {
|
|
63788
63819
|
const deleted = this.cache.delete(key);
|
|
63789
63820
|
if (deleted) {
|
|
@@ -63916,6 +63947,7 @@ class StampedeProtectedCache {
|
|
|
63916
63947
|
const existingPromise = this.pendingRefreshes.get(key);
|
|
63917
63948
|
if (existingPromise) {
|
|
63918
63949
|
this.stats.coalescedRequests++;
|
|
63950
|
+
this.emitEvent("coalesced", key);
|
|
63919
63951
|
this.options.logger.debug("Request coalesced", { key });
|
|
63920
63952
|
return existingPromise;
|
|
63921
63953
|
}
|
|
@@ -63949,6 +63981,7 @@ class StampedeProtectedCache {
|
|
|
63949
63981
|
const timeoutPromise = new Promise((_, reject) => {
|
|
63950
63982
|
timeoutHandle = setTimeout(() => {
|
|
63951
63983
|
this.stats.loadTimeouts++;
|
|
63984
|
+
this.emitEvent("load_timeout", key);
|
|
63952
63985
|
// Mark the invocation abandoned BEFORE evicting the pin: a retry that
|
|
63953
63986
|
// starts now must never be overwritten by this loader's late result.
|
|
63954
63987
|
invocation.abandoned = true;
|
|
@@ -64005,6 +64038,7 @@ class StampedeProtectedCache {
|
|
|
64005
64038
|
}
|
|
64006
64039
|
catch (error) {
|
|
64007
64040
|
this.stats.refreshErrors++;
|
|
64041
|
+
this.emitEvent("refresh_error", key);
|
|
64008
64042
|
const loadTime = Date.now() - startTime;
|
|
64009
64043
|
this.options.logger.error("Failed to load data", {
|
|
64010
64044
|
key,
|
|
@@ -64037,6 +64071,7 @@ class StampedeProtectedCache {
|
|
|
64037
64071
|
this.loadWithCoalescing(key, loader, ttl)
|
|
64038
64072
|
.then(() => {
|
|
64039
64073
|
this.stats.backgroundRefreshes++;
|
|
64074
|
+
this.emitEvent("background_refresh", key);
|
|
64040
64075
|
this.options.logger.debug("Background refresh completed", { key });
|
|
64041
64076
|
})
|
|
64042
64077
|
.catch((error) => {
|