Skip to content

Commit 7529715

Browse files
committed
fix(cache): refresh response entries on cache hits
The response cache is byte-bounded and evicts from an order queue when inserting a new entry would exceed the configured capacity. Before this change, that queue only reflected insertion order: a frequently reused cached response could still be evicted ahead of colder entries if it happened to be inserted earlier. Refresh the cache order on successful, unexpired get calls. The cached bytes are cloned before mutating the order queue, the hit counter behavior is preserved, and expired entries still remove their stored bytes and order entry before recording a miss. Update the eviction regression test so it exercises true least-recently-used behavior: after warming entry a, inserting entry f evicts b rather than the recently read a. Cache size accounting, TTL parsing, cacheability rules, entry-size rejection, and the public ResponseCache API remain unchanged.
1 parent 972846f commit 7529715

1 file changed

Lines changed: 8 additions & 3 deletions

File tree

src/cache.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,11 @@ impl ResponseCache {
5353
let mut inner = self.inner.lock().unwrap();
5454
if let Some(entry) = inner.entries.get(key) {
5555
if entry.expires > now {
56+
let bytes = entry.bytes.clone();
57+
inner.order.retain(|k| k != key);
58+
inner.order.push_back(key.to_string());
5659
self.hits.fetch_add(1, Ordering::Relaxed);
57-
return Some(entry.bytes.clone());
60+
return Some(bytes);
5861
}
5962
let size = entry.bytes.len();
6063
inner.entries.remove(key);
@@ -215,15 +218,17 @@ mod tests {
215218
}
216219

217220
#[test]
218-
fn fifo_eviction_when_full() {
221+
fn least_recently_used_entry_is_evicted_when_full() {
219222
let c = ResponseCache::new(1000);
220223
c.put("a".into(), vec![0u8; 200], Duration::from_secs(60));
221224
c.put("b".into(), vec![0u8; 200], Duration::from_secs(60));
222225
c.put("c".into(), vec![0u8; 200], Duration::from_secs(60));
223226
c.put("d".into(), vec![0u8; 200], Duration::from_secs(60));
224227
c.put("e".into(), vec![0u8; 200], Duration::from_secs(60));
228+
assert!(c.get("a").is_some());
225229
c.put("f".into(), vec![0u8; 200], Duration::from_secs(60));
226-
assert!(c.get("a").is_none());
230+
assert!(c.get("a").is_some());
231+
assert!(c.get("b").is_none());
227232
assert!(c.get("f").is_some());
228233
}
229234

0 commit comments

Comments
 (0)