Skip to content

Commit

Permalink
Add TestCache testing
Browse files Browse the repository at this point in the history
  • Loading branch information
ije committed Jan 25, 2025
1 parent d61ea18 commit b89dc9f
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 20 deletions.
44 changes: 24 additions & 20 deletions server/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ type cacheItem struct {

func withCache[T any](key string, cacheTtl time.Duration, fetch func() (T, string, error)) (data T, err error) {
// check cache store first
if cacheTtl > time.Second {
if cacheTtl > time.Millisecond {
if v, ok := cacheStore.Load(key); ok {
item := v.(*cacheItem)
if item.exp >= time.Now().Unix() {
if item.exp >= time.Now().UnixMilli() {
return item.data.(T), nil
}
}
Expand All @@ -40,10 +40,10 @@ func withCache[T any](key string, cacheTtl time.Duration, fetch func() (T, strin
defer unlock()

// check cache store again after get lock
if cacheTtl > time.Second {
if cacheTtl > time.Millisecond {
if v, ok := cacheStore.Load(key); ok {
item := v.(*cacheItem)
if item.exp >= time.Now().Unix() {
if item.exp >= time.Now().UnixMilli() {
return item.data.(T), nil
}
}
Expand All @@ -55,11 +55,11 @@ func withCache[T any](key string, cacheTtl time.Duration, fetch func() (T, strin
return
}

if cacheTtl > time.Second {
if cacheTtl > time.Millisecond {
exp := time.Now().Add(cacheTtl)
cacheStore.Store(key, &cacheItem{exp.Unix(), data})
cacheStore.Store(key, &cacheItem{exp.UnixMilli(), data})
if aliasKey != "" && aliasKey != key {
cacheStore.Store(aliasKey, &cacheItem{exp.Unix(), data})
cacheStore.Store(aliasKey, &cacheItem{exp.UnixMilli(), data})
}
}
return
Expand Down Expand Up @@ -104,26 +104,30 @@ func withLRUCache[T any](key string, fetch func() (T, error)) (data T, err error
return
}

func gc(now time.Time) {
expKeys := []string{}
cacheStore.Range(func(key, value any) bool {
if !strings.HasPrefix(key.(string), "lru:") {
item := value.(*cacheItem)
if item.exp > 0 && item.exp < now.UnixMilli() {
expKeys = append(expKeys, key.(string))
}
}
return true
})
for _, key := range expKeys {
cacheStore.Delete(key)
}
}

func init() {
cacheLRU = list.New()
// cache GC
go func() {
tick := time.NewTicker(10 * time.Minute)
for {
now := <-tick.C
expKeys := []string{}
cacheStore.Range(func(key, value any) bool {
if !strings.HasPrefix(key.(string), "lru:") {
item := value.(*cacheItem)
if item.exp > 0 && item.exp < now.Unix() {
expKeys = append(expKeys, key.(string))
}
}
return true
})
for _, key := range expKeys {
cacheStore.Delete(key)
}
gc(now)
}
}()
}
44 changes: 44 additions & 0 deletions server/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,46 @@ package server
import (
"fmt"
"testing"
"time"
)

func getCacheSize() int {
size := 0
cacheStore.Range(func(key, value any) bool {
if item, ok := value.(*cacheItem); ok && item.exp >= 0 {
size++
}
return true
})
return size
}

func TestCache(t *testing.T) {
for i := 0; i < 100; i++ {
withCache(fmt.Sprintf("^0.0.%d", i), 10*time.Millisecond, func() ([]byte, string, error) {
return []byte{byte(i)}, fmt.Sprintf("0.0.%d", i), nil
})
}

size := getCacheSize()
if size != 200 {
t.Fatalf("expected 200 items in cache, got %d", size)
}

gc(time.Now())
size = getCacheSize()
if size != 200 {
t.Fatalf("expected 200 items in cache, got %d", size)
}

time.Sleep(100 * time.Millisecond)
gc(time.Now())
size = getCacheSize()
if size != 0 {
t.Fatalf("expected 0 items in cache, got %d", size)
}
}

func TestLRUCache(t *testing.T) {
for i := 0; i < 2000; i++ {
withLRUCache(fmt.Sprintf("item-%d", i), func() ([]byte, error) {
Expand All @@ -14,4 +52,10 @@ func TestLRUCache(t *testing.T) {
if l := cacheLRU.Len(); l != 1000 {
t.Fatalf("expected 1000 items in cache, got %d", l)
}

// the `gc` function does not remove items from the LRU cache
gc(time.Now())
if l := cacheLRU.Len(); l != 1000 {
t.Fatalf("expected 1000 items in cache, got %d", l)
}
}

0 comments on commit b89dc9f

Please sign in to comment.