-
Notifications
You must be signed in to change notification settings - Fork 0
/
cacheInMemory.go
183 lines (158 loc) · 4.03 KB
/
cacheInMemory.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package cacheMemory
import (
"reflect"
"sync"
"time"
"github.com/farseer-go/cache"
"github.com/farseer-go/cache/eumExpiryType"
"github.com/farseer-go/collections"
"github.com/farseer-go/fs/parse"
)
// 二级缓存-本地缓存操作
type cacheInMemory struct {
expiry time.Duration // 设置Memory缓存过期时间
expiryType eumExpiryType.Enum // 过期策略
uniqueField string // hash中的主键(唯一ID的字段名称)
itemType reflect.Type // itemType
key string // 缓存KEY
lock *sync.RWMutex // 锁
data collections.ListAny // 缓存的数据
lastVisitAt time.Time // 最后一次访问时间
}
// 创建实例
func newCache(key string, uniqueField string, itemType reflect.Type, ops ...cache.Option) cache.ICache {
op := &cache.Op{}
for _, option := range ops {
option(op)
}
r := &cacheInMemory{
expiry: op.Expiry,
expiryType: op.ExpiryType,
uniqueField: uniqueField,
itemType: itemType,
key: key,
lock: &sync.RWMutex{},
lastVisitAt: time.Now(),
}
if r.expiry > 0 {
go r.updateTtl()
}
return r
}
func (r *cacheInMemory) Get() collections.ListAny {
r.lock.RLock()
defer r.lock.RUnlock()
// 更新缓存过期时间
r.updateExpiry()
return r.data
}
func (r *cacheInMemory) GetItem(cacheId any) any {
lst := r.Get()
for _, item := range lst.ToArray() {
if cacheId == r.GetUniqueId(item) {
return item
}
}
return nil
}
func (r *cacheInMemory) GetItems(cacheIds []any) collections.ListAny {
keys := collections.NewList[string]()
for _, cacheId := range cacheIds {
keys.Add(parse.ToString(cacheId))
}
lst := r.Get()
items := collections.NewListAny()
for _, item := range lst.ToArray() {
id := r.GetUniqueId(item)
if keys.Contains(id) {
items.Add(item)
}
}
return items
}
func (r *cacheInMemory) Set(val collections.ListAny) {
r.lock.Lock()
defer r.lock.Unlock()
// 更新缓存过期时间
r.updateExpiry()
r.data = val
}
func (r *cacheInMemory) SaveItem(newVal any) {
var list = r.Get()
// 从新对象中,获取唯一标识
newValDataKey := r.GetUniqueId(newVal)
for index := 0; index < list.Count(); index++ {
// 从当前缓存item中,获取唯一标识
itemDataKey := r.GetUniqueId(list.Index(index))
// 找到了
if itemDataKey == newValDataKey {
list.Set(index, newVal)
return
}
}
if list.Count() == 0 {
list = collections.NewListAny()
}
list.Add(newVal)
// 保存
r.Set(list)
}
func (r *cacheInMemory) Remove(cacheId any) {
var list = r.Get()
if list.Count() > 0 {
list.RemoveAll(func(item any) bool { return r.GetUniqueId(item) == cacheId })
}
}
func (r *cacheInMemory) Clear() {
if r.data.Count() > 0 {
r.data.Clear()
}
}
func (r *cacheInMemory) Count() int {
return r.Get().Count()
}
func (r *cacheInMemory) ExistsItem(cacheId any) bool {
var list = r.Get()
if list.Count() == 0 {
return false
}
for index := 0; index < list.Count(); index++ {
// 从当前缓存item中,获取唯一标识
itemDataKey := r.GetUniqueId(list.Index(index))
// 找到了
if itemDataKey == cacheId {
return true
}
}
return false
}
func (r *cacheInMemory) ExistsKey() bool {
r.lock.RLock()
defer r.lock.RUnlock()
return !r.data.IsNil()
}
func (r *cacheInMemory) GetUniqueId(item any) string {
val := reflect.ValueOf(item).FieldByName(r.uniqueField).Interface()
return parse.Convert(val, "")
}
// 更新缓存过期时间
func (r *cacheInMemory) updateExpiry() {
if r.expiry > 0 && r.expiryType == eumExpiryType.SlidingExpiration {
r.lastVisitAt = time.Now()
}
}
// TTL时间到期后没有访问数据,则移除缓存数据
func (r *cacheInMemory) updateTtl() {
ticker := time.NewTicker(r.expiry)
for range ticker.C {
if r.expiryType == eumExpiryType.AbsoluteExpiration || time.Now().Sub(r.lastVisitAt) > r.expiry {
r.lock.Lock()
// 重新计算下一次的失效时间
r.lastVisitAt = time.Time{}
r.Clear()
// 不能使用NewListAny,因为需要data = nil
r.data = collections.ListAny{}
r.lock.Unlock()
}
}
}