This commit is contained in:
2025-03-10 22:20:51 +02:00
parent 0148583f5b
commit cd8c2ee09e
6 changed files with 156 additions and 12 deletions

64
pokecache/pokecache.go Normal file
View File

@@ -0,0 +1,64 @@
package pokecache
import (
"sync"
"time"
)
// Cache -
type Cache struct {
cache map[string]cacheEntry
mux *sync.Mutex
}
type cacheEntry struct {
createdAt time.Time
val []byte
}
// NewCache -
func NewCache(interval time.Duration) Cache {
c := Cache{
cache: make(map[string]cacheEntry),
mux: &sync.Mutex{},
}
go c.reapLoop(interval)
return c
}
// Add -
func (c *Cache) Add(key string, value []byte) {
c.mux.Lock()
defer c.mux.Unlock()
c.cache[key] = cacheEntry{
createdAt: time.Now().UTC(),
val: value,
}
}
// Get -
func (c *Cache) Get(key string) ([]byte, bool) {
c.mux.Lock()
defer c.mux.Unlock()
val, ok := c.cache[key]
return val.val, ok
}
func (c *Cache) reapLoop(interval time.Duration) {
ticker := time.NewTicker(interval)
for range ticker.C {
c.reap(time.Now().UTC(), interval)
}
}
func (c *Cache) reap(now time.Time, last time.Duration) {
c.mux.Lock()
defer c.mux.Unlock()
for k, v := range c.cache {
if v.createdAt.Before(now.Add(-last)) {
delete(c.cache, k)
}
}
}

View File

@@ -0,0 +1,61 @@
package pokecache
import (
"fmt"
"testing"
"time"
)
func TestAddGet(t *testing.T) {
const interval = 5 * time.Second
cases := []struct {
key string
val []byte
}{
{
key: "https://example.com",
val: []byte("testdata"),
},
{
key: "https://example.com/path",
val: []byte("moretestdata"),
},
}
for i, c := range cases {
t.Run(fmt.Sprintf("Test case %v", i), func(t *testing.T) {
cache := NewCache(interval)
cache.Add(c.key, c.val)
val, ok := cache.Get(c.key)
if !ok {
t.Errorf("expected to find key")
return
}
if string(val) != string(c.val) {
t.Errorf("expected to find value")
return
}
})
}
}
func TestReapLoop(t *testing.T) {
const baseTime = 5 * time.Millisecond
const waitTime = baseTime + 5*time.Millisecond
cache := NewCache(baseTime)
cache.Add("https://example.com", []byte("testdata"))
_, ok := cache.Get("https://example.com")
if !ok {
t.Errorf("expected to find key")
return
}
time.Sleep(waitTime)
_, ok = cache.Get("https://example.com")
if ok {
t.Errorf("expected to not find key")
return
}
}