mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
fix nasty bug
This needs to be the opposite check of what we do in Get(). Introduced in a fixup commit.
This commit is contained in:
parent
d16dde36a3
commit
cc76b1a8a7
@ -70,7 +70,7 @@ func (c *Expiring) Get(key interface{}) (val interface{}, ok bool) {
|
|||||||
c.mu.RLock()
|
c.mu.RLock()
|
||||||
defer c.mu.RUnlock()
|
defer c.mu.RUnlock()
|
||||||
e, ok := c.cache[key]
|
e, ok := c.cache[key]
|
||||||
if !ok || c.clock.Now().After(e.expiry) {
|
if !ok || !c.clock.Now().Before(e.expiry) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
return e.val, true
|
return e.val, true
|
||||||
@ -148,7 +148,7 @@ func (c *Expiring) gc(now time.Time) {
|
|||||||
// from looking at the (*expiringHeap).Pop() implmentation below.
|
// from looking at the (*expiringHeap).Pop() implmentation below.
|
||||||
// heap.Pop() swaps the first entry with the last entry of the heap, then
|
// heap.Pop() swaps the first entry with the last entry of the heap, then
|
||||||
// calls (*expiringHeap).Pop() which returns the last element.
|
// calls (*expiringHeap).Pop() which returns the last element.
|
||||||
if len(c.heap) == 0 || now.After(c.heap[0].expiry) {
|
if len(c.heap) == 0 || now.Before(c.heap[0].expiry) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cleanup := heap.Pop(&c.heap).(*expiringHeapEntry)
|
cleanup := heap.Pop(&c.heap).(*expiringHeapEntry)
|
||||||
|
@ -103,6 +103,107 @@ func TestExpiration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGarbageCollection(t *testing.T) {
|
||||||
|
fc := &utilclock.FakeClock{}
|
||||||
|
|
||||||
|
type entry struct {
|
||||||
|
key, val string
|
||||||
|
ttl time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
now time.Time
|
||||||
|
set []entry
|
||||||
|
want map[string]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "two entries just set",
|
||||||
|
now: fc.Now().Add(0 * time.Second),
|
||||||
|
set: []entry{
|
||||||
|
{"a", "aa", 1 * time.Second},
|
||||||
|
{"b", "bb", 2 * time.Second},
|
||||||
|
},
|
||||||
|
want: map[string]string{
|
||||||
|
"a": "aa",
|
||||||
|
"b": "bb",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "first entry expired now",
|
||||||
|
now: fc.Now().Add(1 * time.Second),
|
||||||
|
set: []entry{
|
||||||
|
{"a", "aa", 1 * time.Second},
|
||||||
|
{"b", "bb", 2 * time.Second},
|
||||||
|
},
|
||||||
|
want: map[string]string{
|
||||||
|
"b": "bb",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "first entry expired half a second ago",
|
||||||
|
now: fc.Now().Add(1500 * time.Millisecond),
|
||||||
|
set: []entry{
|
||||||
|
{"a", "aa", 1 * time.Second},
|
||||||
|
{"b", "bb", 2 * time.Second},
|
||||||
|
},
|
||||||
|
want: map[string]string{
|
||||||
|
"b": "bb",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "three entries weird order",
|
||||||
|
now: fc.Now().Add(1 * time.Second),
|
||||||
|
set: []entry{
|
||||||
|
{"c", "cc", 3 * time.Second},
|
||||||
|
{"a", "aa", 1 * time.Second},
|
||||||
|
{"b", "bb", 2 * time.Second},
|
||||||
|
},
|
||||||
|
want: map[string]string{
|
||||||
|
"b": "bb",
|
||||||
|
"c": "cc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "expire multiple entries in one cycle",
|
||||||
|
now: fc.Now().Add(2500 * time.Millisecond),
|
||||||
|
set: []entry{
|
||||||
|
{"a", "aa", 1 * time.Second},
|
||||||
|
{"b", "bb", 2 * time.Second},
|
||||||
|
{"c", "cc", 3 * time.Second},
|
||||||
|
},
|
||||||
|
want: map[string]string{
|
||||||
|
"c": "cc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
c := NewExpiringWithClock(fc)
|
||||||
|
for _, e := range test.set {
|
||||||
|
c.Set(e.key, e.val, e.ttl)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.gc(test.now)
|
||||||
|
|
||||||
|
for k, want := range test.want {
|
||||||
|
got, ok := c.Get(k)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("expected cache to have entry for key=%q but found none", k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("unexpected value for key=%q: got=%q, want=%q", k, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if got, want := c.Len(), len(test.want); got != want {
|
||||||
|
t.Errorf("unexpected cache size: got=%d, want=%d", got, want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkExpiringCacheContention(b *testing.B) {
|
func BenchmarkExpiringCacheContention(b *testing.B) {
|
||||||
b.Run("evict_probablility=100%", func(b *testing.B) {
|
b.Run("evict_probablility=100%", func(b *testing.B) {
|
||||||
benchmarkExpiringCacheContention(b, 1)
|
benchmarkExpiringCacheContention(b, 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user