Priority: Medium
Description
ChainStateCache.getSwr()'s cache-miss path (chain-state-cache.ts:89-92) inserts into this.cache and then calls evictIfNeeded() to enforce maxEntries. The SWR background-refresh path, revalidate() (fired-and-forgotten from line 76), writes this.cache.set(key, {...}) on success at line 112 but never calls evictIfNeeded().
Failure scenario
With maxEntries set small and many distinct keys queried concurrently under load: key A is read as stale, triggers revalidate(A) in the background and is marked isRevalidating. Before A's fetch resolves, enough other keys are inserted to push A out via evictIfNeeded(). When A's revalidate() promise later resolves, it unconditionally re-adds A to cache, bypassing the bound entirely. Repeated across many stale/evicted keys under sustained load, the cache can grow past maxEntries again — reintroducing the unbounded-memory-growth risk that the recent LRU eviction fix (#171 / PR closing #185) was meant to close.
Suggested fix
Call evictIfNeeded() after the cache.set in revalidate()'s success path (line 112), same as the cache-miss path does.
Priority: Medium
Description
ChainStateCache.getSwr()'s cache-miss path (chain-state-cache.ts:89-92) inserts intothis.cacheand then callsevictIfNeeded()to enforcemaxEntries. The SWR background-refresh path,revalidate()(fired-and-forgotten from line 76), writesthis.cache.set(key, {...})on success at line 112 but never callsevictIfNeeded().Failure scenario
With
maxEntriesset small and many distinct keys queried concurrently under load: key A is read as stale, triggersrevalidate(A)in the background and is markedisRevalidating. Before A's fetch resolves, enough other keys are inserted to push A out viaevictIfNeeded(). When A'srevalidate()promise later resolves, it unconditionally re-adds A tocache, bypassing the bound entirely. Repeated across many stale/evicted keys under sustained load, the cache can grow pastmaxEntriesagain — reintroducing the unbounded-memory-growth risk that the recent LRU eviction fix (#171 / PR closing #185) was meant to close.Suggested fix
Call
evictIfNeeded()after thecache.setinrevalidate()'s success path (line 112), same as the cache-miss path does.