@adaptic/utils 0.0.1008 → 0.0.1010
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 +58 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +58 -0
- package/dist/index.mjs.map +1 -1
- package/dist/types/cache/stampede-protected-cache.d.ts +43 -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
|
}
|
|
@@ -63769,6 +63781,29 @@ class StampedeProtectedCache {
|
|
|
63769
63781
|
has(key) {
|
|
63770
63782
|
return this.cache.has(key);
|
|
63771
63783
|
}
|
|
63784
|
+
/**
|
|
63785
|
+
* Synchronous peek at a cached value without triggering a loader.
|
|
63786
|
+
*
|
|
63787
|
+
* @description Returns the cached value when present and FRESH (inside its
|
|
63788
|
+
* per-entry TTL), `undefined` otherwise — never coalesces onto or starts a
|
|
63789
|
+
* load, never serves stale-while-revalidate data, and counts a hit only
|
|
63790
|
+
* when a fresh value is returned (mirroring the read-path hit semantics so
|
|
63791
|
+
* hitRatio stays truthful). Added 2026-08-08 for the engine cache
|
|
63792
|
+
* consolidation: its fork exposed peek() and consumers rely on the
|
|
63793
|
+
* no-load contract on hot paths.
|
|
63794
|
+
*
|
|
63795
|
+
* @param key - Cache key to inspect.
|
|
63796
|
+
* @returns The fresh cached value, or `undefined` when absent or expired.
|
|
63797
|
+
*/
|
|
63798
|
+
peek(key) {
|
|
63799
|
+
const entry = this.cache.get(key);
|
|
63800
|
+
if (entry && Date.now() < entry.expiresAt) {
|
|
63801
|
+
this.stats.hits++;
|
|
63802
|
+
this.emitEvent("hit", key);
|
|
63803
|
+
return entry.value;
|
|
63804
|
+
}
|
|
63805
|
+
return undefined;
|
|
63806
|
+
}
|
|
63772
63807
|
/**
|
|
63773
63808
|
* Delete a specific key from the cache
|
|
63774
63809
|
*
|
|
@@ -63786,6 +63821,25 @@ class StampedeProtectedCache {
|
|
|
63786
63821
|
* cache.delete(`positions:${accountId}`);
|
|
63787
63822
|
* ```
|
|
63788
63823
|
*/
|
|
63824
|
+
/**
|
|
63825
|
+
* Fire the {@link StampedeProtectedCacheOptions.onEvent} hook, never
|
|
63826
|
+
* letting an observer failure propagate into the cache path.
|
|
63827
|
+
*/
|
|
63828
|
+
emitEvent(event, key) {
|
|
63829
|
+
const hook = this.options.onEvent;
|
|
63830
|
+
if (!hook)
|
|
63831
|
+
return;
|
|
63832
|
+
try {
|
|
63833
|
+
hook(event, key);
|
|
63834
|
+
}
|
|
63835
|
+
catch (err) {
|
|
63836
|
+
this.options.logger.warn("cache onEvent observer threw — ignored", {
|
|
63837
|
+
event,
|
|
63838
|
+
key,
|
|
63839
|
+
error: err instanceof Error ? err.message : String(err),
|
|
63840
|
+
});
|
|
63841
|
+
}
|
|
63842
|
+
}
|
|
63789
63843
|
delete(key) {
|
|
63790
63844
|
const deleted = this.cache.delete(key);
|
|
63791
63845
|
if (deleted) {
|
|
@@ -63918,6 +63972,7 @@ class StampedeProtectedCache {
|
|
|
63918
63972
|
const existingPromise = this.pendingRefreshes.get(key);
|
|
63919
63973
|
if (existingPromise) {
|
|
63920
63974
|
this.stats.coalescedRequests++;
|
|
63975
|
+
this.emitEvent("coalesced", key);
|
|
63921
63976
|
this.options.logger.debug("Request coalesced", { key });
|
|
63922
63977
|
return existingPromise;
|
|
63923
63978
|
}
|
|
@@ -63951,6 +64006,7 @@ class StampedeProtectedCache {
|
|
|
63951
64006
|
const timeoutPromise = new Promise((_, reject) => {
|
|
63952
64007
|
timeoutHandle = setTimeout(() => {
|
|
63953
64008
|
this.stats.loadTimeouts++;
|
|
64009
|
+
this.emitEvent("load_timeout", key);
|
|
63954
64010
|
// Mark the invocation abandoned BEFORE evicting the pin: a retry that
|
|
63955
64011
|
// starts now must never be overwritten by this loader's late result.
|
|
63956
64012
|
invocation.abandoned = true;
|
|
@@ -64007,6 +64063,7 @@ class StampedeProtectedCache {
|
|
|
64007
64063
|
}
|
|
64008
64064
|
catch (error) {
|
|
64009
64065
|
this.stats.refreshErrors++;
|
|
64066
|
+
this.emitEvent("refresh_error", key);
|
|
64010
64067
|
const loadTime = Date.now() - startTime;
|
|
64011
64068
|
this.options.logger.error("Failed to load data", {
|
|
64012
64069
|
key,
|
|
@@ -64039,6 +64096,7 @@ class StampedeProtectedCache {
|
|
|
64039
64096
|
this.loadWithCoalescing(key, loader, ttl)
|
|
64040
64097
|
.then(() => {
|
|
64041
64098
|
this.stats.backgroundRefreshes++;
|
|
64099
|
+
this.emitEvent("background_refresh", key);
|
|
64042
64100
|
this.options.logger.debug("Background refresh completed", { key });
|
|
64043
64101
|
})
|
|
64044
64102
|
.catch((error) => {
|