change duration parameter type from interface{} to time.Duration for gcache/gfcache

This commit is contained in:
John
2019-12-04 14:42:09 +08:00
parent 6abe660287
commit 3e27ea0259
5 changed files with 33 additions and 61 deletions

View File

@ -335,13 +335,9 @@ func (md *Model) Batch(batch int) *Model {
// 2. expire参数类型为interface{},这是一个兼容旧版本的方式,该参数支持 int/time.Duration 类型当传递类型为int时表示缓存多少秒。
// 3. name表示自定义的缓存名称注意不要出现重复便于业务层精准定位缓存项(如果业务层需要手动清理时,必须指定缓存名称)
// 例如:查询缓存时设置名称,在特定的业务逻辑中清理缓存时可以给定缓存名称进行精准清理。
func (md *Model) Cache(expire interface{}, name ...string) *Model {
func (md *Model) Cache(expire time.Duration, name ...string) *Model {
model := md.getModel()
if d, ok := expire.(time.Duration); ok {
model.cacheExpire = d
} else {
model.cacheExpire = gconv.Duration(expire) * time.Second
}
model.cacheExpire = expire
if len(name) > 0 {
model.cacheName = name[0]
}

View File

@ -7,6 +7,8 @@
// Package gcache provides high performance and concurrent-safe in-memory cache for process.
package gcache
import "time"
// Default cache object.
var cache = New()
@ -15,7 +17,7 @@ var cache = New()
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func Set(key interface{}, value interface{}, duration interface{}) {
func Set(key interface{}, value interface{}, duration time.Duration) {
cache.Set(key, value, duration)
}
@ -25,7 +27,7 @@ func Set(key interface{}, value interface{}, duration interface{}) {
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func SetIfNotExist(key interface{}, value interface{}, duration interface{}) bool {
func SetIfNotExist(key interface{}, value interface{}, duration time.Duration) bool {
return cache.SetIfNotExist(key, value, duration)
}
@ -34,7 +36,7 @@ func SetIfNotExist(key interface{}, value interface{}, duration interface{}) boo
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func Sets(data map[interface{}]interface{}, duration interface{}) {
func Sets(data map[interface{}]interface{}, duration time.Duration) {
cache.Sets(data, duration)
}
@ -51,7 +53,7 @@ func Get(key interface{}) interface{} {
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func GetOrSet(key interface{}, value interface{}, duration interface{}) interface{} {
func GetOrSet(key interface{}, value interface{}, duration time.Duration) interface{} {
return cache.GetOrSet(key, value, duration)
}
@ -63,7 +65,7 @@ func GetOrSet(key interface{}, value interface{}, duration interface{}) interfac
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func GetOrSetFunc(key interface{}, f func() interface{}, duration interface{}) interface{} {
func GetOrSetFunc(key interface{}, f func() interface{}, duration time.Duration) interface{} {
return cache.GetOrSetFunc(key, f, duration)
}
@ -77,7 +79,7 @@ func GetOrSetFunc(key interface{}, f func() interface{}, duration interface{}) i
// If <duration> <=0 means it does not expire.
//
// Note that the function <f> is executed within writing mutex lock.
func GetOrSetFuncLock(key interface{}, f func() interface{}, duration interface{}) interface{} {
func GetOrSetFuncLock(key interface{}, f func() interface{}, duration time.Duration) interface{} {
return cache.GetOrSetFuncLock(key, f, duration)
}

View File

@ -104,25 +104,13 @@ func (c *memCache) getOrNewExpireSet(expire int64) (expireSet *gset.Set) {
return
}
// getMilliExpire converts parameter <duration> to int type in milliseconds.
//
// Note that there's some performance cost in type assertion here, but it's valuable.
func (c *memCache) getMilliExpire(duration interface{}) int64 {
if d, ok := duration.(time.Duration); ok {
return d.Nanoseconds() / 1000000
} else {
return gconv.Int64(duration)
}
}
// Set sets cache with <key>-<value> pair, which is expired after <duration>.
//
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func (c *memCache) Set(key interface{}, value interface{}, duration interface{}) {
expire := c.getMilliExpire(duration)
expireTime := c.getInternalExpire(expire)
func (c *memCache) Set(key interface{}, value interface{}, duration time.Duration) {
expireTime := c.getInternalExpire(duration.Nanoseconds() / 1000000)
c.dataMu.Lock()
c.data[key] = memCacheItem{v: value, e: expireTime}
c.dataMu.Unlock()
@ -138,9 +126,8 @@ func (c *memCache) Set(key interface{}, value interface{}, duration interface{})
//
// It doubly checks the <key> whether exists in the cache using mutex writing lock
// before setting it to the cache.
func (c *memCache) doSetWithLockCheck(key interface{}, value interface{}, duration interface{}) interface{} {
expire := c.getMilliExpire(duration)
expireTimestamp := c.getInternalExpire(expire)
func (c *memCache) doSetWithLockCheck(key interface{}, value interface{}, duration time.Duration) interface{} {
expireTimestamp := c.getInternalExpire(duration.Nanoseconds() / 1000000)
c.dataMu.Lock()
defer c.dataMu.Unlock()
if v, ok := c.data[key]; ok && !v.IsExpired() {
@ -172,10 +159,9 @@ func (c *memCache) getInternalExpire(expire int64) int64 {
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func (c *memCache) SetIfNotExist(key interface{}, value interface{}, duration interface{}) bool {
expire := c.getMilliExpire(duration)
func (c *memCache) SetIfNotExist(key interface{}, value interface{}, duration time.Duration) bool {
if !c.Contains(key) {
c.doSetWithLockCheck(key, value, expire)
c.doSetWithLockCheck(key, value, duration)
return true
}
return false
@ -186,9 +172,8 @@ func (c *memCache) SetIfNotExist(key interface{}, value interface{}, duration in
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func (c *memCache) Sets(data map[interface{}]interface{}, duration interface{}) {
expire := c.getMilliExpire(duration)
expireTime := c.getInternalExpire(expire)
func (c *memCache) Sets(data map[interface{}]interface{}, duration time.Duration) {
expireTime := c.getInternalExpire(duration.Nanoseconds() / 1000000)
for k, v := range data {
c.dataMu.Lock()
c.data[k] = memCacheItem{v: v, e: expireTime}
@ -220,7 +205,7 @@ func (c *memCache) Get(key interface{}) interface{} {
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func (c *memCache) GetOrSet(key interface{}, value interface{}, duration interface{}) interface{} {
func (c *memCache) GetOrSet(key interface{}, value interface{}, duration time.Duration) interface{} {
if v := c.Get(key); v == nil {
return c.doSetWithLockCheck(key, value, duration)
} else {
@ -236,7 +221,7 @@ func (c *memCache) GetOrSet(key interface{}, value interface{}, duration interfa
// The parameter <duration> can be either type of int or time.Duration.
// If <duration> is type of int, it means <duration> milliseconds.
// If <duration> <=0 means it does not expire.
func (c *memCache) GetOrSetFunc(key interface{}, f func() interface{}, duration interface{}) interface{} {
func (c *memCache) GetOrSetFunc(key interface{}, f func() interface{}, duration time.Duration) interface{} {
if v := c.Get(key); v == nil {
return c.doSetWithLockCheck(key, f(), duration)
} else {
@ -254,7 +239,7 @@ func (c *memCache) GetOrSetFunc(key interface{}, f func() interface{}, duration
// If <duration> <=0 means it does not expire.
//
// Note that the function <f> is executed within writing mutex lock.
func (c *memCache) GetOrSetFuncLock(key interface{}, f func() interface{}, duration interface{}) interface{} {
func (c *memCache) GetOrSetFuncLock(key interface{}, f func() interface{}, duration time.Duration) interface{} {
if v := c.Get(key); v == nil {
return c.doSetWithLockCheck(key, f, duration)
} else {

View File

@ -42,7 +42,7 @@ func TestCache_Set(t *testing.T) {
func TestCache_Set_Expire(t *testing.T) {
gtest.Case(t, func() {
cache := gcache.New()
cache.Set(2, 22, 100)
cache.Set(2, 22, 100*time.Millisecond)
gtest.Assert(cache.Get(2), 22)
time.Sleep(200 * time.Millisecond)
gtest.Assert(cache.Get(2), nil)

View File

@ -18,59 +18,48 @@ import (
const (
// Default expire time for file content caching in seconds.
gDEFAULT_CACHE_EXPIRE = 60
gDEFAULT_CACHE_EXPIRE = time.Minute
)
var (
// Default expire time for file content caching in seconds.
cacheExpire = cmdenv.Get("gf.gfcache.expire", gDEFAULT_CACHE_EXPIRE).Int() * 1000
// Default expire time for file content caching.
cacheExpire = cmdenv.Get("gf.gfcache.expire", gDEFAULT_CACHE_EXPIRE).Duration()
)
// GetContents returns string content of given file by <path> from cache.
// If there's no content in the cache, it will read it from disk file specified by <path>.
// The parameter <expire> specifies the caching time for this file content in seconds.
func GetContents(path string, duration ...interface{}) string {
func GetContents(path string, duration ...time.Duration) string {
return string(GetBinContents(path, duration...))
}
// GetBinContents returns []byte content of given file by <path> from cache.
// If there's no content in the cache, it will read it from disk file specified by <path>.
// The parameter <expire> specifies the caching time for this file content in seconds.
func GetBinContents(path string, duration ...interface{}) []byte {
k := cacheKey(path)
e := cacheExpire
func GetBinContents(path string, duration ...time.Duration) []byte {
key := cacheKey(path)
expire := cacheExpire
if len(duration) > 0 {
e = getSecondExpire(duration[0])
expire = duration[0]
}
r := gcache.GetOrSetFuncLock(k, func() interface{} {
r := gcache.GetOrSetFuncLock(key, func() interface{} {
b := gfile.GetBytes(path)
if b != nil {
// Adding this <path> to gfsnotify,
// it will clear its cache if there's any changes of the file.
_, _ = gfsnotify.Add(path, func(event *gfsnotify.Event) {
gcache.Remove(k)
gcache.Remove(key)
gfsnotify.Exit()
})
}
return b
}, e*1000)
}, expire)
if r != nil {
return r.([]byte)
}
return nil
}
// getSecondExpire converts parameter <duration> to int type in seconds.
//
// Note that there's some performance cost in type assertion here, but it's valuable.
func getSecondExpire(duration interface{}) int {
if d, ok := duration.(time.Duration); ok {
return int(d.Nanoseconds() / 1000000000)
} else {
return duration.(int)
}
}
// cacheKey produces the cache key for gcache.
func cacheKey(path string) string {
return "gf.gfcache:" + path