Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LRU cache #8

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/krakendio/httpcache

go 1.19

require github.com/hashicorp/golang-lru v1.0.2
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
41 changes: 6 additions & 35 deletions httpcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"net/http"
"net/http/httputil"
"strings"
"sync"
"time"
)

Expand Down Expand Up @@ -57,40 +56,6 @@ func CachedResponse(c Cache, req *http.Request) (resp *http.Response, err error)
return http.ReadResponse(bufio.NewReader(b), req)
}

// MemoryCache is an implemtation of Cache that stores responses in an in-memory map.
type MemoryCache struct {
mu sync.RWMutex
items map[string][]byte
}

// Get returns the []byte representation of the response and true if present, false if not
func (c *MemoryCache) Get(key string) (resp []byte, ok bool) {
c.mu.RLock()
resp, ok = c.items[key]
c.mu.RUnlock()
return resp, ok
}

// Set saves response resp to the cache with key
func (c *MemoryCache) Set(key string, resp []byte) {
c.mu.Lock()
c.items[key] = resp
c.mu.Unlock()
}

// Delete removes key from the cache
func (c *MemoryCache) Delete(key string) {
c.mu.Lock()
delete(c.items, key)
c.mu.Unlock()
}

// NewMemoryCache returns a new Cache that will store items in an in-memory map
func NewMemoryCache() *MemoryCache {
c := &MemoryCache{items: map[string][]byte{}}
return c
}

// Transport is an implementation of http.RoundTripper that will return values from a cache
// where possible (avoiding a network request) and will additionally add validators (etag/if-modified-since)
// to repeated requests allowing servers to return 304 / Not Modified
Expand Down Expand Up @@ -552,3 +517,9 @@ func NewMemoryCacheTransport() *Transport {
t := NewTransport(c)
return t
}

func NewLruCacheTransport(size int) *Transport {
c := NewLruCache(size)
t := NewTransport(c)
return t
}
30 changes: 30 additions & 0 deletions lru.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package httpcache

import (
lru "github.com/hashicorp/golang-lru"
)

type LruCache struct {
cache *lru.Cache
}

func NewLruCache(size int) *LruCache {
c, _ := lru.New(size)
return &LruCache{cache: c}
}

func (c *LruCache) Get(key string) ([]byte, bool) {
v, ok := c.cache.Get(key)
if !ok {
return nil, false
}
return v.([]byte), true
}

func (c *LruCache) Set(key string, resp []byte) {
c.cache.Add(key, resp)
}

func (c *LruCache) Delete(key string) {
c.cache.Remove(key)
}
37 changes: 37 additions & 0 deletions memory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package httpcache

import "sync"

// MemoryCache is an implemtation of Cache that stores responses in an in-memory map.
type MemoryCache struct {
mu sync.RWMutex
items map[string][]byte
}

// Get returns the []byte representation of the response and true if present, false if not
func (c *MemoryCache) Get(key string) (resp []byte, ok bool) {
c.mu.RLock()
resp, ok = c.items[key]
c.mu.RUnlock()
return resp, ok
}

// Set saves response resp to the cache with key
func (c *MemoryCache) Set(key string, resp []byte) {
c.mu.Lock()
c.items[key] = resp
c.mu.Unlock()
}

// Delete removes key from the cache
func (c *MemoryCache) Delete(key string) {
c.mu.Lock()
delete(c.items, key)
c.mu.Unlock()
}

// NewMemoryCache returns a new Cache that will store items in an in-memory map
func NewMemoryCache() *MemoryCache {
c := &MemoryCache{items: map[string][]byte{}}
return c
}
4 changes: 4 additions & 0 deletions test/test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ import (
func TestMemoryCache(t *testing.T) {
test.Cache(t, httpcache.NewMemoryCache())
}

func TestLruCache(t *testing.T) {
test.Cache(t, httpcache.NewLruCache(10))
}
Loading