mirror of
https://github.com/gookit/cache.git
synced 2025-09-26 20:21:16 +08:00
up: add more unit tests
This commit is contained in:
@@ -25,11 +25,14 @@ Generic cache use and cache manager for golang. Provide a unified usage API by p
|
||||
- `gocache` https://github.com/patrickmn/go-cache
|
||||
- `bigcache` https://github.com/allegro/bigcache
|
||||
|
||||
internal:
|
||||
Internal:
|
||||
|
||||
- file internal driver [driver_file.go](driver_file.go)
|
||||
- memory internal driver [driver_memory.go](driver_memory.go)
|
||||
|
||||
> Notice: The built-in implementation is relatively simple and is not recommended for production environments;
|
||||
> the production environment recommends using the third-party drivers listed above.
|
||||
|
||||
## GoDoc
|
||||
|
||||
- [doc on gowalker](https://gowalker.org/github.com/gookit/cache)
|
||||
@@ -53,8 +56,6 @@ type Cache interface {
|
||||
// basic operation
|
||||
Has(key string) bool
|
||||
Get(key string) interface{}
|
||||
// GetAs get cache value and unmarshal to an object ptr.
|
||||
GetAs(key string, ptr interface{}) error
|
||||
Set(key string, val interface{}, ttl time.Duration) (err error)
|
||||
Del(key string) error
|
||||
// multi operation
|
||||
|
@@ -26,11 +26,13 @@ Golang 通用的缓存管理使用库。
|
||||
- `gocache` https://github.com/patrickmn/go-cache
|
||||
- `bigcache` https://github.com/allegro/bigcache
|
||||
|
||||
internal:
|
||||
Internal:
|
||||
|
||||
- file 简单的文件缓存(_当前包的内置实现_)
|
||||
- memory 简单的内存缓存(_当前包的内置实现_)
|
||||
|
||||
> 注意:内置实现比较简单,不推荐生产环境使用;生产环境推荐使用上面列出的三方驱动。
|
||||
|
||||
## GoDoc
|
||||
|
||||
- [doc on gowalker](https://gowalker.org/github.com/gookit/cache)
|
||||
@@ -53,8 +55,6 @@ type Cache interface {
|
||||
// basic op
|
||||
Has(key string) bool
|
||||
Get(key string) interface{}
|
||||
// GetAs get cache value and unmarshal to an object ptr.
|
||||
GetAs(key string, ptr interface{}) error
|
||||
Set(key string, val interface{}, ttl time.Duration) (err error)
|
||||
Del(key string) error
|
||||
// multi op
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
"go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
// Name driver name
|
||||
const Name = "boltDB"
|
||||
|
||||
// BoltDB definition
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
// Memory open a file that does not persist to disk.
|
||||
const Memory = ":memory:"
|
||||
// Name driver name
|
||||
const Name = "buntDB"
|
||||
|
||||
// BuntDB definition.
|
||||
|
18
cache.go
18
cache.go
@@ -88,13 +88,13 @@ func Register(name string, driver Cache) *Manager {
|
||||
}
|
||||
|
||||
// Unregister an cache driver
|
||||
func Unregister(name string) {
|
||||
std.Unregister(name)
|
||||
func Unregister(name string) int {
|
||||
return std.Unregister(name)
|
||||
}
|
||||
|
||||
// UnregisterAll cache drivers
|
||||
func UnregisterAll(fn ...func(cache Cache)) {
|
||||
std.UnregisterAll(fn...)
|
||||
func UnregisterAll(fn ...func(cache Cache)) int {
|
||||
return std.UnregisterAll(fn...)
|
||||
}
|
||||
|
||||
// SetDefName set default driver name.
|
||||
@@ -124,6 +124,11 @@ func Driver(driverName string) Cache {
|
||||
return std.Driver(driverName)
|
||||
}
|
||||
|
||||
// Std get default cache manager instance
|
||||
func Std() *Manager {
|
||||
return std
|
||||
}
|
||||
|
||||
// DefManager get default cache manager instance
|
||||
func DefManager() *Manager {
|
||||
return std
|
||||
@@ -139,6 +144,11 @@ func Close() error {
|
||||
return std.Close()
|
||||
}
|
||||
|
||||
// ClearAll all drivers caches
|
||||
func ClearAll() error {
|
||||
return std.ClearAll()
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* quick use by default cache driver
|
||||
*************************************************************/
|
||||
|
@@ -49,15 +49,9 @@ func NewFileCache(dir string, pfxAndKey ...string) *FileCache {
|
||||
return c
|
||||
}
|
||||
|
||||
// Has cache key.
|
||||
// TODO decode value, and check expire time
|
||||
// Has cache key. will check expire time
|
||||
func (c *FileCache) Has(key string) bool {
|
||||
if c.MemoryCache.Has(key) {
|
||||
return true
|
||||
}
|
||||
|
||||
path := c.GetFilename(key)
|
||||
return fileExists(path)
|
||||
return c.get(key) != nil
|
||||
}
|
||||
|
||||
// Get value by key
|
||||
@@ -87,17 +81,16 @@ func (c *FileCache) get(key string) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// check expire time
|
||||
if item.Exp == 0 || item.Exp > time.Now().Unix() {
|
||||
c.caches[key] = item // save to memory.
|
||||
return item.Val
|
||||
}
|
||||
|
||||
// has been expired. delete it.
|
||||
// check expired
|
||||
if item.Expired() {
|
||||
c.SetLastErr(c.del(key))
|
||||
return nil
|
||||
}
|
||||
|
||||
c.caches[key] = item // save to memory.
|
||||
return item.Val
|
||||
}
|
||||
|
||||
// Set value by key
|
||||
func (c *FileCache) Set(key string, val interface{}, ttl time.Duration) (err error) {
|
||||
c.lock.Lock()
|
||||
@@ -107,8 +100,8 @@ func (c *FileCache) Set(key string, val interface{}, ttl time.Duration) (err err
|
||||
}
|
||||
|
||||
func (c *FileCache) set(key string, val interface{}, ttl time.Duration) (err error) {
|
||||
if err = c.MemoryCache.set(key, val, ttl); err != nil {
|
||||
c.SetLastErr(err)
|
||||
err = c.MemoryCache.set(key, val, ttl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -132,10 +125,7 @@ func (c *FileCache) set(key string, val interface{}, ttl time.Duration) (err err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err = f.Write(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = f.Write(bs)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -165,12 +155,12 @@ func (c *FileCache) GetMulti(keys []string) map[string]interface{} {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
values := make(map[string]interface{}, len(keys))
|
||||
data := make(map[string]interface{}, len(keys))
|
||||
for _, key := range keys {
|
||||
values[key] = c.get(key)
|
||||
data[key] = c.get(key)
|
||||
}
|
||||
|
||||
return values
|
||||
return data
|
||||
}
|
||||
|
||||
// SetMulti values by multi key
|
||||
|
@@ -5,16 +5,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// MemoryCache definition.
|
||||
type MemoryCache struct {
|
||||
// locker
|
||||
lock sync.RWMutex
|
||||
// cache data in memory. or use sync.Map
|
||||
caches map[string]*Item
|
||||
// TODO set max cache number
|
||||
MaxCacheNum int
|
||||
}
|
||||
|
||||
// Item for memory cache
|
||||
type Item struct {
|
||||
// Exp expire time
|
||||
@@ -23,9 +13,19 @@ type Item struct {
|
||||
Val interface{}
|
||||
}
|
||||
|
||||
// Invalid check whether expired
|
||||
func (item Item) Invalid() bool {
|
||||
return item.Exp != 0 && item.Exp < time.Now().Unix()
|
||||
// Expired check whether expired
|
||||
func (item Item) Expired() bool {
|
||||
return item.Exp > 1 && item.Exp < time.Now().Unix()
|
||||
}
|
||||
|
||||
// MemoryCache definition.
|
||||
type MemoryCache struct {
|
||||
// locker
|
||||
lock sync.RWMutex
|
||||
// cache data in memory. or use sync.Map
|
||||
caches map[string]*Item
|
||||
// CacheSize TODO set max cache size
|
||||
CacheSize int
|
||||
}
|
||||
|
||||
// NewMemoryCache create a memory cache instance
|
||||
@@ -53,9 +53,8 @@ func (c *MemoryCache) Get(key string) interface{} {
|
||||
|
||||
func (c *MemoryCache) get(key string) interface{} {
|
||||
if item, ok := c.caches[key]; ok {
|
||||
// check expire time
|
||||
// if has been expired, remove it.
|
||||
if item.Invalid() {
|
||||
// check expire time. if has been expired, remove it.
|
||||
if item.Expired() {
|
||||
_ = c.del(key)
|
||||
}
|
||||
|
||||
|
@@ -122,3 +122,33 @@ func TestFileCache_object(t *testing.T) {
|
||||
// val2 := c.GetAs()
|
||||
// dump.P("cache get:", val)
|
||||
}
|
||||
|
||||
func TestDefManager(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
num := cache.UnregisterAll()
|
||||
is.Equal(0, num)
|
||||
is.Equal(0, cache.Unregister("not_exist"))
|
||||
|
||||
cache.Register(cache.DvrMemory, cache.NewMemoryCache())
|
||||
is.Equal(cache.DvrMemory, cache.Std().DefName())
|
||||
|
||||
key := "name"
|
||||
|
||||
// set
|
||||
err := cache.Set(key, "cache value", cache.TwoMinutes)
|
||||
is.NoError(err)
|
||||
is.True(cache.Has(key))
|
||||
|
||||
// get
|
||||
val := cache.Get(key)
|
||||
is.Equal("cache value", val)
|
||||
|
||||
// del
|
||||
is.NoError(cache.Del(key))
|
||||
is.False(cache.Has(key))
|
||||
|
||||
is.NoError(cache.Clear())
|
||||
|
||||
num = cache.UnregisterAll()
|
||||
is.GreaterOrEqual(1, num)
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ func Example() {
|
||||
cache.Register(goredis.Name, goredis.Connect("127.0.0.1:6379", "", 0))
|
||||
|
||||
// setting default driver name
|
||||
cache.DefaultUse(cache.DvrRedis)
|
||||
cache.DefaultUse(goredis.Name)
|
||||
|
||||
// quick use.(it is default driver)
|
||||
//
|
||||
|
@@ -7,6 +7,9 @@ import (
|
||||
"github.com/bluele/gcache"
|
||||
)
|
||||
|
||||
// Name driver name
|
||||
const Name = "gcache"
|
||||
|
||||
// GCache driver definition
|
||||
type GCache struct {
|
||||
// cache.BaseDriver
|
||||
|
122
gcache/gcache_test.go
Normal file
122
gcache/gcache_test.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package gcache_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gookit/cache"
|
||||
"github.com/gookit/cache/gcache"
|
||||
"github.com/gookit/goutil/dump"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
c := gcache.New(12)
|
||||
key := "name"
|
||||
|
||||
// set
|
||||
c.Set(key, "cache value", cache.Seconds2)
|
||||
fmt.Println(c.Has(key))
|
||||
|
||||
// get
|
||||
val := c.Get(key)
|
||||
fmt.Println(val)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// get expired
|
||||
val2 := c.Get(key)
|
||||
fmt.Println(val2)
|
||||
|
||||
// del
|
||||
c.Del(key)
|
||||
fmt.Println(c.Has(key))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// cache value
|
||||
// <nil>
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleGCache_in_cachePkg() {
|
||||
cache.Register(gcache.Name, gcache.New(12))
|
||||
defer cache.UnregisterAll()
|
||||
|
||||
key := "name1"
|
||||
|
||||
// set
|
||||
cache.Set(key, "cache value", cache.Seconds2)
|
||||
fmt.Println(cache.Has(key))
|
||||
|
||||
// get
|
||||
val := cache.Get(key)
|
||||
fmt.Println(val)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// get expired
|
||||
val2 := cache.Get(key)
|
||||
fmt.Println(val2)
|
||||
|
||||
// del
|
||||
cache.Del(key)
|
||||
fmt.Println(cache.Has(key))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// cache value
|
||||
// <nil>
|
||||
// false
|
||||
}
|
||||
|
||||
func TestGCache_usage(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
c := gcache.New(12)
|
||||
defer c.Clear()
|
||||
|
||||
key := strutil.RandomCharsV2(12)
|
||||
is.False(c.Has(key))
|
||||
|
||||
err := c.Set(key, "value", cache.Seconds3)
|
||||
is.NoError(err)
|
||||
is.True(c.Has(key))
|
||||
|
||||
val := c.Get(key)
|
||||
is.Equal("value", val)
|
||||
|
||||
// del
|
||||
err = c.Del(key)
|
||||
is.NoError(err)
|
||||
is.False(c.Has(key))
|
||||
}
|
||||
|
||||
type user struct {
|
||||
Age int
|
||||
Name string
|
||||
}
|
||||
|
||||
func TestGCache_object(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
c := gcache.New(12)
|
||||
defer c.Clear()
|
||||
|
||||
b1 := user {
|
||||
Age: 1,
|
||||
Name: "inhere",
|
||||
}
|
||||
|
||||
key := strutil.RandomCharsV2(12)
|
||||
dump.P("cache key: " + key)
|
||||
is.False(c.Has(key))
|
||||
|
||||
err := c.Set(key, b1, cache.Seconds3)
|
||||
is.NoError(err)
|
||||
is.True(c.Has(key))
|
||||
|
||||
b2 := c.Get(key).(user)
|
||||
dump.P(b2)
|
||||
is.Equal("inhere", b2.Name)
|
||||
}
|
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func ExampleGoCache() {
|
||||
func Example() {
|
||||
c := gocache.New()
|
||||
key := "name"
|
||||
|
||||
@@ -41,7 +41,7 @@ func ExampleGoCache() {
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleNewGoCache_cachePkg() {
|
||||
func ExampleGoCache_in_cachePkg() {
|
||||
c1 := gocache.NewGoCache(cache.OneDay, cache.FiveMinutes)
|
||||
cache.Register(gocache.Name, c1)
|
||||
defer cache.UnregisterAll()
|
||||
|
@@ -7,6 +7,9 @@ import (
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
// Name driver name
|
||||
const Name = "leveldb"
|
||||
|
||||
// LevelDB definition
|
||||
type LevelDB struct {
|
||||
// cache.BaseDriver
|
||||
|
24
manager.go
24
manager.go
@@ -43,13 +43,18 @@ func (m *Manager) Register(name string, driver Cache) *Manager {
|
||||
}
|
||||
|
||||
// Unregister an cache driver
|
||||
func (m *Manager) Unregister(name string) {
|
||||
func (m *Manager) Unregister(name string) int {
|
||||
if _, ok := m.drivers[name]; !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
delete(m.drivers, name)
|
||||
|
||||
// reset default driver name.
|
||||
if m.defName == name {
|
||||
m.defName = ""
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// SetDefName set default driver name. alias of DefaultUse()
|
||||
@@ -106,10 +111,20 @@ func (m *Manager) Close() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// UnregisterAll cache drivers
|
||||
func (m *Manager) UnregisterAll(fn ...func(cache Cache)) {
|
||||
m.defName = ""
|
||||
// ClearAll all drivers caches
|
||||
func (m *Manager) ClearAll() (err error) {
|
||||
for _, cache := range m.drivers {
|
||||
err = cache.Clear()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// UnregisterAll cache drivers
|
||||
func (m *Manager) UnregisterAll(fn ...func(cache Cache)) int {
|
||||
num := len(m.drivers)
|
||||
|
||||
// unregister
|
||||
m.defName = ""
|
||||
for name, driver := range m.drivers {
|
||||
if len(fn) > 0 {
|
||||
fn[0](driver)
|
||||
@@ -117,6 +132,7 @@ func (m *Manager) UnregisterAll(fn ...func(cache Cache)) {
|
||||
|
||||
delete(m.drivers, name)
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
|
@@ -8,6 +8,9 @@ import (
|
||||
"github.com/gookit/cache"
|
||||
)
|
||||
|
||||
// Name driver name
|
||||
const Name = "memCached"
|
||||
|
||||
// MemCached definition
|
||||
type MemCached struct {
|
||||
cache.BaseDriver
|
||||
|
@@ -5,6 +5,9 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Name driver name
|
||||
const Name = "nutsdb"
|
||||
|
||||
// NutsDB definition TODO
|
||||
type NutsDB struct {
|
||||
// cache.BaseDriver
|
||||
|
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/gookit/cache"
|
||||
)
|
||||
|
||||
// Name driver name
|
||||
const Name = "redigo"
|
||||
|
||||
// RedisCache fallback alias
|
||||
|
Reference in New Issue
Block a user