feat: implemented poke api client with cache

This commit is contained in:
Stevan Freeborn
2026-07-28 07:34:17 -05:00
parent c78ff443a6
commit 68b34ec28f
5 changed files with 399 additions and 2 deletions
+76
View File
@@ -0,0 +1,76 @@
package pokecache
import (
"sync"
"time"
)
type cacheEntry struct {
val []byte
createdAt time.Time
}
type Cache struct {
entries map[string]cacheEntry
lock sync.Mutex
done chan struct{}
once sync.Once
}
func NewCache(interval time.Duration) *Cache {
c := Cache{
entries: map[string]cacheEntry{},
done: make(chan struct{}),
}
go c.runReapLoop(interval)
return &c
}
func (c *Cache) runReapLoop(interval time.Duration) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
c.lock.Lock()
for k, v := range c.entries {
if time.Since(v.createdAt) > interval {
delete(c.entries, k)
}
}
c.lock.Unlock()
case <-c.done:
return
}
}
}
func (c *Cache) Add(key string, value []byte) {
c.lock.Lock()
defer c.lock.Unlock()
c.entries[key] = cacheEntry{
val: value,
createdAt: time.Now(),
}
}
func (c *Cache) Get(key string) ([]byte, bool) {
c.lock.Lock()
defer c.lock.Unlock()
v, ok := c.entries[key]
return v.val, ok
}
func (c *Cache) Stop() {
c.once.Do(func() {
close(c.done)
})
}
+64
View File
@@ -0,0 +1,64 @@
package pokecache_test
import (
"testing"
"time"
"github.com/StevanFreeborn/pokedexcli/internal/pokecache"
)
func TestNewCache(t *testing.T) {
t.Run("it should return new initialized cache", func(t *testing.T) {
cache := pokecache.NewCache(5 * time.Second)
defer cache.Stop()
if cache == nil {
t.Errorf("expected result to be non nil value")
}
})
t.Run("it should start reaping loop", func(t *testing.T) {
interval := 1 * time.Second
wait := interval + 1
key := "key"
bytes := []byte("Hello World")
cache := pokecache.NewCache(1 * time.Second)
defer cache.Stop()
cache.Add(key, bytes)
time.Sleep(wait)
_, found := cache.Get(key)
if found {
t.Errorf("expected entry for key %s to have been reaped", key)
}
})
}
func TestAdd(t *testing.T) {
t.Run("it should add entry to cache and allow retrieving entry", func(t *testing.T) {
key := "key"
bytes := []byte("Hello World")
cache := pokecache.NewCache(5 * time.Second)
defer cache.Stop()
cache.Add(key, bytes)
result, found := cache.Get(key)
if !found {
t.Errorf("expected to find entry for key %s", key)
}
expected := string(bytes)
strResult := string(result)
if strResult != expected {
t.Errorf("expected to find value %s for key %s but received %s", expected, key, strResult)
}
})
}