2 Star 1 Fork 1

mosache/YFrame

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
local_cache.go 2.58 KB
一键复制 编辑 原始数据 按行查看 历史
ヤ沒脩袮兲︶ 提交于 2023-07-31 22:35 . temp
package localCache
import (
"context"
"errors"
"gitee.com/mosache/YFrame/cache"
"gitee.com/mosache/YFrame/cache/errs"
"sync"
"time"
)
/*
LocalCache
local cache build in map
*/
type LocalCache struct {
data map[string]*item
mutex sync.RWMutex
checkInterval time.Duration // 检测循环间隔时间
checkLoopMaxCheckCount int // 每次循环最大检测key个数
close chan struct{}
evictFunc EvictFunc
}
var _ cache.Cache = &LocalCache{}
type EvictFunc func(key string, val any)
type item struct {
val any
expireTime time.Time
}
type Opt func(c *LocalCache)
func New(opts ...Opt) *LocalCache {
lc := &LocalCache{
data: make(map[string]*item),
checkInterval: time.Second * 10,
close: make(chan struct{}),
checkLoopMaxCheckCount: 100,
evictFunc: func(key string, val any) {},
}
for _, e := range opts {
e(lc)
}
/// check key expiration loop
go func() {
ticker := time.NewTicker(lc.checkInterval)
for {
select {
case <-lc.close:
ticker.Stop()
case t := <-ticker.C:
i := 0
lc.mutex.Lock()
for k, v := range lc.data {
/// 每次只随机检测指定个数
if i == lc.checkLoopMaxCheckCount {
break
}
/// key过期
if v.expired(t) {
lc.delete(k)
}
i++
}
lc.mutex.Unlock()
}
}
}()
return lc
}
func (l *LocalCache) Get(ctx context.Context, key string) (any, error) {
l.mutex.RLock()
val, ok := l.data[key]
l.mutex.RUnlock()
if !ok {
return nil, errs.ErrKeyNotFound(key)
}
now := time.Now()
if val.expired(now) {
l.mutex.Lock()
val, ok = l.data[key]
defer l.mutex.Unlock()
if val.expired(now) {
l.delete(key)
return nil, errs.ErrKeyNotFound(key)
}
}
return val.val, nil
}
func (l *LocalCache) Set(ctx context.Context, key string, val any, expireTime time.Duration) error {
l.mutex.Lock()
defer l.mutex.Unlock()
l.data[key] = &item{
val: val,
expireTime: time.Now().Add(expireTime),
}
return nil
}
func (l *LocalCache) Delete(ctx context.Context, key string) error {
l.mutex.Lock()
defer l.mutex.Unlock()
l.delete(key)
return nil
}
func (l *LocalCache) delete(key string) {
val, ok := l.data[key]
if !ok {
return
}
delete(l.data, key)
l.evictFunc(key, val)
}
func (l *LocalCache) Close() error {
select {
case l.close <- struct{}{}:
default:
return errors.New("close already")
}
return nil
}
func (i *item) expired(now time.Time) bool {
return !i.expireTime.IsZero() && i.expireTime.Before(now)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/mosache/YFrame.git
git@gitee.com:mosache/YFrame.git
mosache
YFrame
YFrame
v0.1.75

搜索帮助