-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
ttl-cache.ts
54 lines (50 loc) · 1.55 KB
/
ttl-cache.ts
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
/**
* An in-memory cache with a configurable TTL (time to live) which means cache items
* expire after they have been in the cache longer than that time.
*
* The `ttl` config option is in milliseconds. Defaults to 30 seconds TTL and a cache size of 1000.
*/
export class TtlCache<K, V> {
private cache = new Map<K, { value: V; expires: number }>();
private readonly ttl: number = 30 * 1000;
private readonly cacheSize: number = 1000;
constructor(config?: { ttl?: number; cacheSize?: number }) {
if (config?.ttl) {
this.ttl = config.ttl;
}
if (config?.cacheSize) {
this.cacheSize = config.cacheSize;
}
}
get(key: K): V | undefined {
const hit = this.cache.get(key);
const now = new Date().getTime();
if (hit) {
if (now < hit.expires) {
return hit.value;
} else {
this.cache.delete(key);
}
}
}
set(key: K, value: V) {
if (this.cache.has(key)) {
// delete key to put the item to the end of
// the cache, marking it as new again
this.cache.delete(key);
} else if (this.cache.size === this.cacheSize) {
// evict oldest
this.cache.delete(this.first());
}
this.cache.set(key, {
value,
expires: new Date().getTime() + this.ttl,
});
}
delete(key: K) {
this.cache.delete(key);
}
private first() {
return this.cache.keys().next().value;
}
}