Skip to content

Commit 33a1490

Browse files
committed
added more tests for janitor
1 parent 04fe7d7 commit 33a1490

File tree

5 files changed

+56
-31
lines changed

5 files changed

+56
-31
lines changed

cache.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,12 @@ type Cache[K comparable, V any] struct {
9191
type Option[K comparable, V any] func(*options[K, V])
9292

9393
type options[K comparable, V any] struct {
94-
ctx context.Context
9594
cache Interface[K, *Item[K, V]]
9695
janitorInterval time.Duration
9796
}
9897

9998
func newOptions[K comparable, V any]() *options[K, V] {
10099
return &options[K, V]{
101-
ctx: context.Background(),
102100
cache: simple.NewCache[K, *Item[K, V]](),
103101
janitorInterval: time.Minute,
104102
}
@@ -149,25 +147,23 @@ func WithJanitorInterval[K comparable, V any](d time.Duration) Option[K, V] {
149147
}
150148

151149
// New creates a new thread safe Cache.
150+
// This function will be stopped an internal janitor when the cache is
151+
// no longer referenced anywhere.
152152
//
153153
// There are several Cache replacement policies available with you specified any options.
154154
func New[K comparable, V any](opts ...Option[K, V]) *Cache[K, V] {
155155
o := newOptions[K, V]()
156156
for _, optFunc := range opts {
157157
optFunc(o)
158158
}
159+
ctx, cancel := context.WithCancel(context.Background())
159160
cache := &Cache[K, V]{
160-
cache: o.cache,
161-
}
162-
if o.ctx == context.Background() {
163-
ctx, cancel := context.WithCancel(o.ctx)
164-
cache.janitor = newJanitor(ctx, o.janitorInterval)
165-
runtime.SetFinalizer(cache, func(self *Cache[K, V]) {
166-
cancel()
167-
})
168-
} else {
169-
cache.janitor = newJanitor(o.ctx, o.janitorInterval)
161+
cache: o.cache,
162+
janitor: newJanitor(ctx, o.janitorInterval),
170163
}
164+
runtime.SetFinalizer(cache, func(self *Cache[K, V]) {
165+
cancel()
166+
})
171167
return cache
172168
}
173169

@@ -181,7 +177,7 @@ func NewContext[K comparable, V any](ctx context.Context, opts ...Option[K, V])
181177
}
182178
return &Cache[K, V]{
183179
cache: o.cache,
184-
janitor: newJanitor(o.ctx, o.janitorInterval),
180+
janitor: newJanitor(ctx, o.janitorInterval),
185181
}
186182
}
187183

cache_internal_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package cache
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
)
8+
9+
func TestDeletedCache(t *testing.T) {
10+
ctx, cancel := context.WithCancel(context.Background())
11+
defer cancel()
12+
13+
nc := NewContext[string, int](ctx)
14+
key := "key"
15+
nc.Set(key, 1, WithExpiration(-time.Second))
16+
17+
_, ok := nc.cache.Get(key)
18+
if !ok {
19+
t.Fatal("want true")
20+
}
21+
22+
nc.DeleteExpired()
23+
24+
_, ok = nc.cache.Get(key)
25+
if ok {
26+
t.Fatal("want false")
27+
}
28+
}

cache_test.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"math/rand"
55
"sync"
66
"testing"
7-
"time"
87

98
cache "github.com/Code-Hex/go-generics-cache"
109
"github.com/Code-Hex/go-generics-cache/policy/clock"
@@ -14,23 +13,6 @@ import (
1413
"github.com/Code-Hex/go-generics-cache/policy/mru"
1514
)
1615

17-
func TestExpiration(t *testing.T) {
18-
nc := cache.New[string, int]()
19-
nc.Set("hello", 1, cache.WithExpiration(3*time.Second))
20-
21-
time.Sleep(time.Second * 1)
22-
result, got := nc.Get("hello")
23-
if !got || result != 1 {
24-
t.Errorf("no, expiration must exists")
25-
}
26-
27-
time.Sleep(time.Second * 3)
28-
result, got = nc.Get("hello")
29-
if got || result == 1 {
30-
t.Errorf("no, expiration must not exists")
31-
}
32-
}
33-
3416
func TestMultiThreadIncr(t *testing.T) {
3517
nc := cache.NewNumber[string, int]()
3618
nc.Set("counter", 0)

example_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cache_test
22

33
import (
4+
"context"
45
"fmt"
56
"time"
67

@@ -20,6 +21,23 @@ func ExampleCache() {
2021
// 0 false
2122
}
2223

24+
func ExampleNewContext() {
25+
ctx, cancel := context.WithCancel(context.Background())
26+
defer cancel()
27+
28+
// use simple cache algorithm without options.
29+
// an internal janitor will be stopped if specified the context is cancelled.
30+
c := cache.NewContext(ctx, cache.WithJanitorInterval[string, int](3*time.Second))
31+
c.Set("a", 1)
32+
gota, aok := c.Get("a")
33+
gotb, bok := c.Get("b")
34+
fmt.Println(gota, aok)
35+
fmt.Println(gotb, bok)
36+
// Output:
37+
// 1 true
38+
// 0 false
39+
}
40+
2341
func ExampleAsClock() {
2442
// use clock cache algorithm.
2543
c := cache.New(cache.AsClock[string, int]())

janitor.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ func (j *janitor) run(cleanup func()) {
3636
case <-ticker.C:
3737
cleanup()
3838
case <-j.done:
39+
cleanup() // last call
3940
return
4041
case <-j.ctx.Done():
4142
j.stop()

0 commit comments

Comments
 (0)