mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-11 19:04:35 +00:00
use disk backed cache (#289)
This commit is contained in:
71
pkg/cache/cache.go
vendored
71
pkg/cache/cache.go
vendored
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/micro/micro/v3/service/logger"
|
||||
"github.com/micro/micro/v3/service/store"
|
||||
"github.com/micro/services/pkg/tenant"
|
||||
"github.com/peterbourgon/diskv/v3"
|
||||
)
|
||||
|
||||
type Cache interface {
|
||||
@@ -23,11 +24,14 @@ type Cache interface {
|
||||
Delete(key string) error
|
||||
Increment(key string, val int64) (int64, error)
|
||||
Decrement(key string, val int64) (int64, error)
|
||||
Close() error
|
||||
}
|
||||
|
||||
type cache struct {
|
||||
sync.Mutex
|
||||
closed chan bool
|
||||
LRU *lru.Cache
|
||||
Disk *diskv.Diskv
|
||||
Store store.Store
|
||||
Prefix string
|
||||
}
|
||||
@@ -48,12 +52,28 @@ var (
|
||||
|
||||
func New(st store.Store) Cache {
|
||||
l, _ := lru.New(DefaultCacheSize)
|
||||
d := diskv.New(diskv.Options{
|
||||
BasePath: "cache",
|
||||
})
|
||||
|
||||
return &cache{
|
||||
LRU: l,
|
||||
Disk: d,
|
||||
Store: st,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cache) run() {
|
||||
for {
|
||||
select {
|
||||
case <-c.closed:
|
||||
return
|
||||
case <-time.After(time.Hour):
|
||||
c.Disk.EraseAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cache) Key(k string) string {
|
||||
if len(c.Prefix) > 0 {
|
||||
return fmt.Sprintf("%s/%s", c.Prefix, k)
|
||||
@@ -67,12 +87,28 @@ func (c *cache) Context(ctx context.Context) Cache {
|
||||
return c
|
||||
}
|
||||
return &cache{
|
||||
closed: make(chan bool),
|
||||
LRU: c.LRU,
|
||||
Disk: c.Disk,
|
||||
Store: c.Store,
|
||||
Prefix: t,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cache) Close() error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
select {
|
||||
case <-c.closed:
|
||||
return nil
|
||||
default:
|
||||
close(c.closed)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *cache) Get(key string, val interface{}) error {
|
||||
k := c.Key(key)
|
||||
|
||||
@@ -94,6 +130,25 @@ func (c *cache) Get(key string, val interface{}) error {
|
||||
|
||||
logger.Infof("Cache miss for %v", k)
|
||||
|
||||
if c.Disk == nil {
|
||||
c.Disk = diskv.New(diskv.Options{
|
||||
BasePath: "cache",
|
||||
})
|
||||
}
|
||||
|
||||
// read from disk
|
||||
b, err := c.Disk.Read(k)
|
||||
if err == nil && len(b) > 0 {
|
||||
var i item
|
||||
if err := json.Unmarshal(b, &i); err == nil {
|
||||
if !i.expires.IsZero() && i.expires.Sub(time.Now()).Seconds() < 0 {
|
||||
c.Disk.Erase(k)
|
||||
return ErrNotFound
|
||||
}
|
||||
return json.Unmarshal(i.val, val)
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise check the store
|
||||
if c.Store == nil {
|
||||
c.Store = store.DefaultStore
|
||||
@@ -119,7 +174,13 @@ func (c *cache) Get(key string, val interface{}) error {
|
||||
if rec.Expiry > time.Duration(0) {
|
||||
expires = time.Now().Add(rec.Expiry)
|
||||
}
|
||||
c.LRU.Add(rec.Key, &item{key: rec.Key, val: rec.Value, expires: expires})
|
||||
|
||||
vi := &item{key: rec.Key, val: rec.Value, expires: expires}
|
||||
c.LRU.Add(rec.Key, vi)
|
||||
|
||||
b, _ = json.Marshal(vi)
|
||||
// put on disk
|
||||
c.Disk.Write(rec.Key, b)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -146,7 +207,11 @@ func (c *cache) Set(key string, val interface{}, expires time.Time) error {
|
||||
}
|
||||
|
||||
// set in the lru
|
||||
c.LRU.Add(rec.Key, &item{key: rec.Key, val: rec.Value, expires: expires})
|
||||
vi := &item{key: rec.Key, val: rec.Value, expires: expires}
|
||||
c.LRU.Add(rec.Key, vi)
|
||||
b, _ = json.Marshal(vi)
|
||||
// put on disk
|
||||
c.Disk.Write(rec.Key, b)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -158,6 +223,8 @@ func (c *cache) Delete(key string) error {
|
||||
k := c.Key(key)
|
||||
// remove from the lru
|
||||
c.LRU.Remove(k)
|
||||
// remove from disk
|
||||
c.Disk.Erase(k)
|
||||
// delete from the store
|
||||
return c.Store.Delete(k)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user