mirror of
https://github.com/status-im/nim-libp2p.git
synced 2025-02-19 16:24:25 +00:00
feat: add maxSize to TimedCache (#1132)
This commit is contained in:
parent
2195313dba
commit
78f0855419
@ -29,6 +29,7 @@ type
|
|||||||
head, tail: TimedEntry[K] # nim linked list doesn't allow inserting at pos
|
head, tail: TimedEntry[K] # nim linked list doesn't allow inserting at pos
|
||||||
entries: HashSet[TimedEntry[K]]
|
entries: HashSet[TimedEntry[K]]
|
||||||
timeout: Duration
|
timeout: Duration
|
||||||
|
maxSize: int # Optional max size of the cache, 0 means unlimited
|
||||||
|
|
||||||
func `==`*[E](a, b: TimedEntry[E]): bool =
|
func `==`*[E](a, b: TimedEntry[E]): bool =
|
||||||
if isNil(a) == isNil(b):
|
if isNil(a) == isNil(b):
|
||||||
@ -78,7 +79,18 @@ func put*[K](t: var TimedCache[K], k: K, now = Moment.now()): bool =
|
|||||||
# Puts k in cache, returning true if the item was already present and false
|
# Puts k in cache, returning true if the item was already present and false
|
||||||
# otherwise. If the item was already present, its expiry timer will be
|
# otherwise. If the item was already present, its expiry timer will be
|
||||||
# refreshed.
|
# refreshed.
|
||||||
|
func ensureSizeBound(t: var TimedCache[K]) =
|
||||||
|
if t.maxSize > 0 and t.entries.len() >= t.maxSize and k notin t:
|
||||||
|
if t.head != nil:
|
||||||
|
t.entries.excl(t.head)
|
||||||
|
t.head = t.head.next
|
||||||
|
if t.head != nil:
|
||||||
|
t.head.prev = nil
|
||||||
|
else:
|
||||||
|
t.tail = nil
|
||||||
|
|
||||||
t.expire(now)
|
t.expire(now)
|
||||||
|
t.ensureSizeBound()
|
||||||
|
|
||||||
let
|
let
|
||||||
previous = t.del(k) # Refresh existing item
|
previous = t.del(k) # Refresh existing item
|
||||||
@ -128,5 +140,5 @@ func addedAt*[K](t: var TimedCache[K], k: K): Moment =
|
|||||||
|
|
||||||
default(Moment)
|
default(Moment)
|
||||||
|
|
||||||
func init*[K](T: type TimedCache[K], timeout: Duration = Timeout): T =
|
func init*[K](T: type TimedCache[K], timeout: Duration = Timeout, maxSize: int = 0): T =
|
||||||
T(timeout: timeout)
|
T(timeout: timeout, maxSize: maxSize)
|
||||||
|
@ -57,3 +57,93 @@ suite "TimedCache":
|
|||||||
for i in 101 .. 100000:
|
for i in 101 .. 100000:
|
||||||
check:
|
check:
|
||||||
i in cache
|
i in cache
|
||||||
|
|
||||||
|
test "max size constraint":
|
||||||
|
var cache = TimedCache[int].init(5.seconds, 3) # maxSize = 3
|
||||||
|
|
||||||
|
let now = Moment.now()
|
||||||
|
check:
|
||||||
|
not cache.put(1, now)
|
||||||
|
not cache.put(2, now + 1.seconds)
|
||||||
|
not cache.put(3, now + 2.seconds)
|
||||||
|
|
||||||
|
check:
|
||||||
|
1 in cache
|
||||||
|
2 in cache
|
||||||
|
3 in cache
|
||||||
|
|
||||||
|
check:
|
||||||
|
not cache.put(4, now + 3.seconds) # exceeds maxSize, evicts 1
|
||||||
|
|
||||||
|
check:
|
||||||
|
1 notin cache
|
||||||
|
2 in cache
|
||||||
|
3 in cache
|
||||||
|
4 in cache
|
||||||
|
|
||||||
|
check:
|
||||||
|
not cache.put(5, now + 4.seconds) # exceeds maxSize, evicts 2
|
||||||
|
|
||||||
|
check:
|
||||||
|
1 notin cache
|
||||||
|
2 notin cache
|
||||||
|
3 in cache
|
||||||
|
4 in cache
|
||||||
|
5 in cache
|
||||||
|
|
||||||
|
check:
|
||||||
|
not cache.put(6, now + 5.seconds) # exceeds maxSize, evicts 3
|
||||||
|
|
||||||
|
check:
|
||||||
|
1 notin cache
|
||||||
|
2 notin cache
|
||||||
|
3 notin cache
|
||||||
|
4 in cache
|
||||||
|
5 in cache
|
||||||
|
6 in cache
|
||||||
|
|
||||||
|
test "max size with expiration":
|
||||||
|
var cache = TimedCache[int].init(3.seconds, 2) # maxSize = 2
|
||||||
|
|
||||||
|
let now = Moment.now()
|
||||||
|
check:
|
||||||
|
not cache.put(1, now)
|
||||||
|
not cache.put(2, now + 1.seconds)
|
||||||
|
|
||||||
|
check:
|
||||||
|
1 in cache
|
||||||
|
2 in cache
|
||||||
|
|
||||||
|
check:
|
||||||
|
not cache.put(3, now + 5.seconds) # expires 1 and 2, should only contain 3
|
||||||
|
|
||||||
|
check:
|
||||||
|
1 notin cache
|
||||||
|
2 notin cache
|
||||||
|
3 in cache
|
||||||
|
|
||||||
|
test "max size constraint with refresh":
|
||||||
|
var cache = TimedCache[int].init(5.seconds, 3) # maxSize = 3
|
||||||
|
|
||||||
|
let now = Moment.now()
|
||||||
|
check:
|
||||||
|
not cache.put(1, now)
|
||||||
|
not cache.put(2, now + 1.seconds)
|
||||||
|
not cache.put(3, now + 2.seconds)
|
||||||
|
|
||||||
|
check:
|
||||||
|
1 in cache
|
||||||
|
2 in cache
|
||||||
|
3 in cache
|
||||||
|
|
||||||
|
check:
|
||||||
|
cache.put(1, now + 3.seconds) # refreshes 1, now 2 is the oldest
|
||||||
|
|
||||||
|
check:
|
||||||
|
not cache.put(4, now + 3.seconds) # exceeds maxSize, evicts 2
|
||||||
|
|
||||||
|
check:
|
||||||
|
1 in cache
|
||||||
|
2 notin cache
|
||||||
|
3 in cache
|
||||||
|
4 in cache
|
||||||
|
Loading…
x
Reference in New Issue
Block a user