Skip to content

Commit

Permalink
feat: add LRU cache
Browse files Browse the repository at this point in the history
  • Loading branch information
shaj13 committed May 23, 2020
1 parent 1fd9228 commit 9191354
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/shaj13/go-guardian
go 1.13

require (
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
github.com/gorilla/sessions v1.2.0
github.com/stretchr/testify v1.5.1
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
Expand Down
40 changes: 40 additions & 0 deletions store/lru.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package store

import (
"net/http"
"sync"

"github.com/golang/groupcache/lru"
)

// LRU implements a fixed-size thread safe LRU cache.
// It is based on the LRU cache in Groupcache.
type LRU struct {
Cache *lru.Cache
MU *sync.Mutex
}

// Load returns the value stored in the Cache for a key, or nil if no value is present.
// The ok result indicates whether value was found in the Cache.
func (l *LRU) Load(key string, _ *http.Request) (interface{}, bool, error) {
l.MU.Lock()
defer l.MU.Unlock()
v, ok := l.Cache.Get(key)
return v, ok, nil
}

// Store sets the value for a key.
func (l *LRU) Store(key string, value interface{}, _ *http.Request) error {
l.MU.Lock()
defer l.MU.Unlock()
l.Cache.Add(key, value)
return nil
}

// Delete the value for a key.
func (l *LRU) Delete(key string, r *http.Request) error {
l.MU.Lock()
defer l.MU.Unlock()
l.Cache.Remove(key)
return nil
}
94 changes: 94 additions & 0 deletions store/lru_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package store

import (
"net/http"
"sync"
"testing"

"github.com/golang/groupcache/lru"
"github.com/stretchr/testify/assert"
)

func TestLRU(t *testing.T) {
table := []struct {
name string
key string
value interface{}
op string
expectedErr bool
found bool
}{
{
name: "it return false when key does not exist",
op: "load",
key: "key",
found: false,
},
{
name: "it return true and value when exist",
op: "load",
key: "test",
value: "test",
found: true,
},
{
name: "it overwrite exist key and value when store",
op: "store",
key: "test",
value: "test2",
found: true,
},
{
name: "it create new record when store",
op: "store",
key: "key",
value: "value",
found: true,
},
{
name: "it's not crash when trying to delete a non exist record",
key: "key",
found: false,
},
{
name: "it delete a exist record",
op: "delete",
key: "test",
found: false,
},
}

for _, tt := range table {
t.Run(tt.name, func(t *testing.T) {
cache := &LRU{
Cache: lru.New(2),
MU: &sync.Mutex{},
}

cache.Cache.Add("test", "test")

r, _ := http.NewRequest("GET", "/", nil)
var err error

switch tt.op {
case "load":
v, ok, err := cache.Load(tt.key, r)
assert.Equal(t, tt.value, v)
assert.Equal(t, tt.found, ok)
assert.NoError(t, err)
return
case "store":
err = cache.Store(tt.key, tt.value, r)
case "delete":
err = cache.Delete(tt.key, r)
}

v, ok := cache.Cache.Get(tt.key)
assert.NoError(t, err)
assert.Equal(t, tt.found, ok)
assert.Equal(t, tt.value, v)

})
}

}

0 comments on commit 9191354

Please sign in to comment.