1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use fibre_cache::CacheBuilder;
use std::{thread, time::Duration};
const TINY_TTI: Duration = Duration::from_millis(200);
const JANITOR_TICK: Duration = Duration::from_millis(50);
// A sleep duration safely longer than the TTI
const SLEEP_DURATION: Duration = Duration::from_millis(400);
#[test]
fn test_sync_item_expires_after_tti() {
let cache = CacheBuilder::<&str, &str>::new()
.shards(1)
.time_to_idle(TINY_TTI)
.janitor_tick_interval(JANITOR_TICK)
.maintenance_chance(1)
.build()
.unwrap();
cache.insert("key", "value", 1);
// Wait for TTI to expire
thread::sleep(SLEEP_DURATION);
// The get call will see the item is expired and return None.
// At this point, the item might still be in the cache map, waiting for the janitor.
assert!(
cache.fetch(&"key").is_none(),
"Item should be identified as expired on get"
);
// Wait a little longer to give the janitor time to run and update the eviction metric.
thread::sleep(JANITOR_TICK * 2);
assert_eq!(
cache.metrics().evicted_by_tti,
1,
"TTI eviction metric should be updated by janitor"
);
}
#[test]
fn test_sync_tti_is_reset_on_access() {
let cache = CacheBuilder::<&str, &str>::new()
.shards(1)
.time_to_idle(TINY_TTI)
.janitor_tick_interval(JANITOR_TICK)
.maintenance_chance(1)
.build()
.unwrap();
cache.insert("key", "value", 1);
// Loop several times, each time sleeping for less than the TTI
// and then accessing the key to reset the idle timer.
for _ in 0..3 {
thread::sleep(TINY_TTI / 2);
assert!(
cache.fetch(&"key").is_some(),
"Item should be present before TTI expires"
);
}
// Now, wait for the full TTI duration without access
thread::sleep(SLEEP_DURATION);
// The item should finally be expired.
assert!(
cache.fetch(&"key").is_none(),
"Item should have expired after final idle period"
);
}