Skip to content

Commit ec2f5f5

Browse files
committed
expire check interval bluele#77
2 parents d8b7e05 + 7529929 commit ec2f5f5

8 files changed

Lines changed: 174 additions & 23 deletions

File tree

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,28 @@ added key: 1
312312
added key: 2
313313
```
314314

315+
## Interval
316+
### Expire check interval
317+
```go
318+
func main () {
319+
gc := gcache.New(10).
320+
LRU().
321+
EvictedFunc(func(key, value interface{}) {
322+
fmt.Printf("key: [%v] evicted\n", key)
323+
}).
324+
ExpireCheckInterval(300 * time.Millisecond).
325+
Build()
326+
327+
_ = gc.SetWithExpire(1, 1, time.Second)
328+
329+
time.Sleep(time.Second * 2)
330+
}
331+
```
332+
333+
```
334+
key: [1] evicted
335+
```
336+
315337
# Author
316338

317339
**Jun Kimura**

arc.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,31 @@ func (c *ARC) init() {
3232
c.t2 = newARCList()
3333
c.b1 = newARCList()
3434
c.b2 = newARCList()
35+
36+
if c.expireCheckInterval != nil && *c.expireCheckInterval != 0 {
37+
go func() {
38+
for range time.Tick(*c.expireCheckInterval) {
39+
for key := range c.items {
40+
now := time.Now()
41+
c.checkAndDeleteExpire(key, &now)
42+
}
43+
}
44+
}()
45+
}
46+
}
47+
48+
func (c *ARC) checkAndDeleteExpire(key interface{}, now *time.Time) {
49+
c.mu.Lock()
50+
defer c.mu.Unlock()
51+
52+
item, ok := c.items[key]
53+
if !ok {
54+
return
55+
}
56+
57+
if item.IsExpired(now) {
58+
c.remove(key)
59+
}
3560
}
3661

3762
func (c *ARC) replace(key interface{}) {

cache.go

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,18 @@ type Cache interface {
4949
}
5050

5151
type baseCache struct {
52-
clock Clock
53-
size int
54-
loaderExpireFunc LoaderExpireFunc
55-
evictedFunc EvictedFunc
56-
purgeVisitorFunc PurgeVisitorFunc
57-
addedFunc AddedFunc
58-
deserializeFunc DeserializeFunc
59-
serializeFunc SerializeFunc
60-
expiration *time.Duration
61-
mu sync.RWMutex
62-
loadGroup Group
52+
clock Clock
53+
size int
54+
loaderExpireFunc LoaderExpireFunc
55+
evictedFunc EvictedFunc
56+
purgeVisitorFunc PurgeVisitorFunc
57+
addedFunc AddedFunc
58+
deserializeFunc DeserializeFunc
59+
serializeFunc SerializeFunc
60+
expiration *time.Duration
61+
expireCheckInterval *time.Duration
62+
mu sync.RWMutex
63+
loadGroup Group
6364
*stats
6465
}
6566

@@ -74,16 +75,17 @@ type (
7475
)
7576

7677
type CacheBuilder struct {
77-
clock Clock
78-
tp string
79-
size int
80-
loaderExpireFunc LoaderExpireFunc
81-
evictedFunc EvictedFunc
82-
purgeVisitorFunc PurgeVisitorFunc
83-
addedFunc AddedFunc
84-
expiration *time.Duration
85-
deserializeFunc DeserializeFunc
86-
serializeFunc SerializeFunc
78+
clock Clock
79+
tp string
80+
size int
81+
loaderExpireFunc LoaderExpireFunc
82+
evictedFunc EvictedFunc
83+
purgeVisitorFunc PurgeVisitorFunc
84+
addedFunc AddedFunc
85+
expiration *time.Duration
86+
expireCheckInterval *time.Duration
87+
deserializeFunc DeserializeFunc
88+
serializeFunc SerializeFunc
8789
}
8890

8991
func New(size int) *CacheBuilder {
@@ -168,6 +170,11 @@ func (cb *CacheBuilder) Expiration(expiration time.Duration) *CacheBuilder {
168170
return cb
169171
}
170172

173+
func (cb *CacheBuilder) ExpireCheckInterval(expireCheckInterval time.Duration) *CacheBuilder {
174+
cb.expireCheckInterval = &expireCheckInterval
175+
return cb
176+
}
177+
171178
func (cb *CacheBuilder) Build() Cache {
172179
if cb.size <= 0 && cb.tp != TYPE_SIMPLE {
173180
panic("gcache: Cache size <= 0")
@@ -201,6 +208,7 @@ func buildCache(c *baseCache, cb *CacheBuilder) {
201208
c.serializeFunc = cb.serializeFunc
202209
c.evictedFunc = cb.evictedFunc
203210
c.purgeVisitorFunc = cb.purgeVisitorFunc
211+
c.expireCheckInterval = cb.expireCheckInterval
204212
c.stats = &stats{}
205213
}
206214

examples/autoloading/autoloading_cache.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ func main() {
99
gc := gcache.New(10).
1010
LFU().
1111
LoaderFunc(func(key interface{}) (interface{}, error) {
12-
return fmt.Sprintf("%v-value", key), nil
13-
}).
12+
return fmt.Sprintf("%v-value", key), nil
13+
}).
1414
Build()
1515

1616
v, err := gc.Get("key")
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/bluele/gcache"
6+
"time"
7+
)
8+
9+
func main() {
10+
gc := gcache.New(10).
11+
LRU().
12+
EvictedFunc(func(key, value interface{}) {
13+
fmt.Printf("key: [%v] evicted\n", key)
14+
}).
15+
ExpireCheckInterval(300 * time.Millisecond).
16+
Build()
17+
18+
_ = gc.SetWithExpire(1, 1, time.Second)
19+
20+
time.Sleep(time.Second * 2)
21+
}

lfu.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,31 @@ func (c *LFUCache) init() {
4343
freq: 0,
4444
items: make(map[*lfuItem]struct{}),
4545
})
46+
47+
if c.expireCheckInterval != nil && *c.expireCheckInterval != 0 {
48+
go func() {
49+
for range time.Tick(*c.expireCheckInterval) {
50+
for key := range c.items {
51+
now := time.Now()
52+
c.checkAndDeleteExpire(key, &now)
53+
}
54+
}
55+
}()
56+
}
57+
}
58+
59+
func (c *LFUCache) checkAndDeleteExpire(key interface{}, now *time.Time) {
60+
c.mu.Lock()
61+
defer c.mu.Unlock()
62+
63+
item, ok := c.items[key]
64+
if !ok {
65+
return
66+
}
67+
68+
if item.IsExpired(now) {
69+
c.remove(key)
70+
}
4671
}
4772

4873
// Set a new key-value pair

lru.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,31 @@ func newLRUCache(cb *CacheBuilder) *LRUCache {
2424
func (c *LRUCache) init() {
2525
c.evictList = list.New()
2626
c.items = make(map[interface{}]*list.Element, c.size+1)
27+
28+
if c.expireCheckInterval != nil && *c.expireCheckInterval != 0 {
29+
go func() {
30+
for range time.Tick(*c.expireCheckInterval) {
31+
for key := range c.items {
32+
now := time.Now()
33+
c.checkAndDeleteExpire(key, &now)
34+
}
35+
}
36+
}()
37+
}
38+
}
39+
40+
func (c *LRUCache) checkAndDeleteExpire(key interface{}, now *time.Time) {
41+
c.mu.Lock()
42+
defer c.mu.Unlock()
43+
44+
item, ok := c.items[key]
45+
if !ok {
46+
return
47+
}
48+
49+
if item.Value.(*lruItem).IsExpired(now) {
50+
c.remove(key)
51+
}
2752
}
2853

2954
func (c *LRUCache) set(key, value interface{}) (interface{}, error) {

simple.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,31 @@ func (c *SimpleCache) init() {
2525
} else {
2626
c.items = make(map[interface{}]*simpleItem, c.size)
2727
}
28+
29+
if c.expireCheckInterval != nil && *c.expireCheckInterval != 0 {
30+
go func() {
31+
for range time.Tick(*c.expireCheckInterval) {
32+
for key := range c.items {
33+
now := time.Now()
34+
c.checkAndDeleteExpire(key, &now)
35+
}
36+
}
37+
}()
38+
}
39+
}
40+
41+
func (c *SimpleCache) checkAndDeleteExpire(key interface{}, now *time.Time) {
42+
c.mu.Lock()
43+
defer c.mu.Unlock()
44+
45+
item, ok := c.items[key]
46+
if !ok {
47+
return
48+
}
49+
50+
if item.IsExpired(now) {
51+
c.remove(key)
52+
}
2853
}
2954

3055
// Set a new key-value pair

0 commit comments

Comments
 (0)