🎨 update memory storage

This commit is contained in:
Fenny
2020-10-31 10:16:11 +01:00
parent 7c012ee154
commit c14befe194
8 changed files with 107 additions and 66 deletions

1
go.mod
View File

@@ -5,6 +5,7 @@ go 1.14
require (
github.com/aws/aws-sdk-go v1.35.19 // indirect
github.com/go-redis/redis/v8 v8.3.3
github.com/gofiber/fiber/v2 v2.1.2
github.com/gofiber/utils v0.0.10
github.com/golang/snappy v0.0.2 // indirect
github.com/gomodule/redigo v1.8.2

11
go.sum
View File

@@ -1,4 +1,5 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPIk=
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/aws/aws-sdk-go v1.35.19 h1:vdIqQnOIqTNtvnOdt9r3Bf/FiCJ7KV/7O2BIj4TPx2w=
@@ -43,6 +44,9 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
github.com/gofiber/fiber v1.14.6 h1:QRUPvPmr8ijQuGo1MgupHBn8E+wW0IKqiOvIZPtV70o=
github.com/gofiber/fiber/v2 v2.1.2 h1:b4rpt9xtj7LxT1Vp3yR76LOfs6ZzPJybbNMjjpn+fos=
github.com/gofiber/fiber/v2 v2.1.2/go.mod h1:jMNH7iuOJ1AGdoJrx1OwaZIX7SOrQUtJi9R35QWhi4s=
github.com/gofiber/utils v0.0.10 h1:3Mr7X7JdCUo7CWf/i5sajSaDmArEDtti8bM1JUVso2U=
github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -75,6 +79,7 @@ github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaR
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M=
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ=
github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -122,6 +127,9 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc h1:n+nNi93yXLkJvKwXNP9d55HC7lGK4H/SRcwB5IaUZLo=
@@ -143,6 +151,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -166,8 +175,10 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=

View File

@@ -5,5 +5,5 @@ An in-memory storage driver.
### Creation
```go
store := memoryStore.New()
store := memory.New()
```

21
memory/config.go Normal file
View File

@@ -0,0 +1,21 @@
package memory
import "time"
// Config defines the config for memory storage.
type Config struct {
GCInterval time.Duration
}
// ConfigDefault is the default config
var ConfigDefault = Config{
GCInterval: 10 * time.Second,
}
// Helper function to set default values
func configDefault(cfg Config) Config {
if int(cfg.GCInterval) == 0 {
cfg.GCInterval = ConfigDefault.GCInterval
}
return cfg
}

View File

@@ -1,5 +0,0 @@
module github.com/gofiber/storage/memory
go 1.15
require github.com/gofiber/utils v0.0.10

View File

@@ -1,2 +0,0 @@
github.com/gofiber/utils v0.0.10 h1:3Mr7X7JdCUo7CWf/i5sajSaDmArEDtti8bM1JUVso2U=
github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo=

View File

@@ -1,88 +1,103 @@
package memoryStore
package memory
import (
"sync"
"time"
)
func New() *MemoryStore {
ms := &MemoryStore{
data: make(map[string]dataPoint),
gcInterval: time.Second * 10,
}
go ms.gc()
return ms
}
type MemoryStore struct {
// Storage interface that is implemented by storage providers
type Storage struct {
mux sync.RWMutex
data map[string]dataPoint
db map[string]entry
gcInterval time.Duration
}
type dataPoint struct {
type entry struct {
data []byte
expiry int64
}
func (ms *MemoryStore) Get(id string) ([]byte, error) {
ms.mux.RLock()
v, ok := ms.data[id]
ms.mux.RUnlock()
// New creates a new memory storage
func New(config ...Config) *Storage {
// Set default config
cfg := ConfigDefault
// Override config if provided
if len(config) > 0 {
cfg = configDefault(config[0])
}
// Create storage
store := &Storage{
db: make(map[string]entry),
gcInterval: cfg.GCInterval,
}
// start garbage collector
go store.gc()
return store
}
// Get value by key
func (s *Storage) Get(key string) ([]byte, error) {
s.mux.RLock()
v, ok := s.db[key]
s.mux.RUnlock()
if !ok {
return []byte{}, nil
return nil, nil
}
if v.expiry < time.Now().Unix() && v.expiry != 0 {
ms.Delete(id)
return []byte{}, nil
s.Delete(key)
return nil, nil
}
return v.data, nil
}
func (ms *MemoryStore) Set(id string, val []byte, expiration time.Duration) error {
var expirationTime int64
if expiration != 0 {
expirationTime = time.Now().Add(expiration).Unix()
// Set key with value
func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
var expire int64
if exp != 0 {
expire = time.Now().Add(exp).Unix()
}
ms.mux.Lock()
ms.data[id] = dataPoint{val, expirationTime}
ms.mux.Unlock()
s.mux.Lock()
s.db[key] = entry{val, expire}
s.mux.Unlock()
return nil
}
func (ms *MemoryStore) Delete(id string) error {
ms.mux.Lock()
delete(ms.data, id)
ms.mux.Unlock()
// Delete key by key
func (s *Storage) Delete(key string) error {
s.mux.Lock()
delete(s.db, key)
s.mux.Unlock()
return nil
}
func (ms *MemoryStore) Clear() error {
ms.mux.Lock()
ms.data = make(map[string]dataPoint)
ms.mux.Unlock()
// Clear all keys
func (s *Storage) Clear() error {
s.mux.Lock()
s.db = make(map[string]entry)
s.mux.Unlock()
return nil
}
func (ms *MemoryStore) gc() {
tick := time.NewTicker(ms.gcInterval)
func (s *Storage) gc() {
tick := time.NewTicker(s.gcInterval)
for {
<-tick.C
ms.mux.Lock()
s.mux.Lock()
now := time.Now().Unix()
for id, v := range ms.data {
for id, v := range s.db {
if v.expiry < now && v.expiry != 0 {
delete(ms.data, id)
delete(s.db, id)
}
}
ms.mux.Unlock()
s.mux.Unlock()
}
}

View File

@@ -1,10 +1,10 @@
package memoryStore
package memory
import (
"testing"
"time"
"github.com/gofiber/utils"
"github.com/gofiber/fiber/v2/utils"
)
func Test_Set(t *testing.T) {
@@ -16,7 +16,7 @@ func Test_Set(t *testing.T) {
store.Set(id, value, 0)
utils.AssertEqual(t, dataPoint{value, 0}, store.data[id])
utils.AssertEqual(t, entry{value, 0}, store.db[id])
}
@@ -31,7 +31,7 @@ func Test_SetExpiry(t *testing.T) {
store.Set(id, value, expiry)
now := time.Now().Unix()
fromStore, found := store.data[id]
fromStore, found := store.db[id]
utils.AssertEqual(t, true, found)
delta := fromStore.expiry - now
@@ -47,8 +47,8 @@ func Test_SetExpiry(t *testing.T) {
func Test_GC(t *testing.T) {
// New() isn't being used here so the gcInterval can be set low
store := &MemoryStore{
data: make(map[string]dataPoint),
store := &Storage{
db: make(map[string]entry),
gcInterval: time.Second * 1,
}
go store.gc()
@@ -58,11 +58,11 @@ func Test_GC(t *testing.T) {
expireAt := time.Now().Add(time.Second * 2).Unix()
store.data[id] = dataPoint{value, expireAt}
store.db[id] = entry{value, expireAt}
time.Sleep(time.Second * 4) // The purpose of the long delay is to ensure the GC has time to run and delete the value
_, found := store.data[id]
_, found := store.db[id]
utils.AssertEqual(t, false, found)
}
@@ -74,7 +74,7 @@ func Test_Get(t *testing.T) {
id := "hello"
value := []byte("Hi there!")
store.data[id] = dataPoint{value, 0}
store.db[id] = entry{value, 0}
returnedValue, err := store.Get(id)
utils.AssertEqual(t, nil, err)
@@ -89,12 +89,12 @@ func Test_Delete(t *testing.T) {
id := "hello"
value := []byte("Hi there!")
store.data[id] = dataPoint{value, 0}
store.db[id] = entry{value, 0}
err := store.Delete(id)
utils.AssertEqual(t, nil, err)
_, found := store.data[id]
_, found := store.db[id]
utils.AssertEqual(t, false, found)
}
@@ -106,11 +106,11 @@ func Test_Clear(t *testing.T) {
id := "hello"
value := []byte("Hi there!")
store.data[id] = dataPoint{value, 0}
store.db[id] = entry{value, 0}
err := store.Clear()
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, make(map[string]dataPoint), store.data)
utils.AssertEqual(t, make(map[string]entry), store.db)
}
@@ -137,7 +137,7 @@ func Benchmark_Get(b *testing.B) {
id := "hello"
value := []byte("Hi there!")
store.data[id] = dataPoint{value, 0}
store.db[id] = entry{value, 0}
b.ResetTimer()