Skip to content

Commit 6e63277

Browse files
committed
fixed simple cache
1 parent 6621c1b commit 6e63277

File tree

5 files changed

+110
-10
lines changed

5 files changed

+110
-10
lines changed

cache.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import (
99
type Cache[K comparable, V any] interface {
1010
Get(key K) (value V, ok bool)
1111
Set(key K, val V, opts ...ItemOption)
12+
Keys() []K
13+
Delete(key K)
14+
Contains(key K) bool
1215
}
1316

1417
// Item is an item

lru/lru_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,4 @@ func TestDelete(t *testing.T) {
6262
if _, ok := cache.Get("foo"); ok {
6363
t.Fatalf("invalid get after deleted %v", ok)
6464
}
65-
6665
}

simple/example_test.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package simple_test
22

33
import (
44
"fmt"
5-
"sort"
65
"time"
76

87
cache "github.com/Code-Hex/go-generics-cache"
@@ -19,24 +18,29 @@ func ExampleCache() {
1918
fmt.Println(av, aok)
2019
fmt.Println(bv, bok)
2120
fmt.Println(cv, cok)
21+
c.Delete("a")
22+
_, aok2 := c.Get("a")
23+
if !aok2 {
24+
fmt.Println("key 'a' has been deleted")
25+
}
2226
// Output:
2327
// 1 true
2428
// 2 true
2529
// 0 false
30+
// key 'a' has been deleted
2631
}
2732

2833
func ExampleCacheKeys() {
2934
c := simple.NewCache[string, int]()
30-
c.Set("a", 1)
31-
c.Set("b", 2)
32-
c.Set("c", 3)
35+
c.Set("foo", 1)
36+
c.Set("bar", 2)
37+
c.Set("baz", 3)
3338
keys := c.Keys()
34-
sort.Strings(keys)
3539
for _, key := range keys {
3640
fmt.Println(key)
3741
}
3842
// Output:
39-
// a
40-
// b
41-
// c
43+
// foo
44+
// bar
45+
// baz
4246
}

simple/simple.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package simple
22

33
import (
4+
"sort"
45
"sync"
56

67
cache "github.com/Code-Hex/go-generics-cache"
@@ -45,11 +46,37 @@ func (c *Cache[K, V]) Get(k K) (val V, ok bool) {
4546
return got.Value, true
4647
}
4748

48-
// Keys returns cache keys. the order is random.
49+
// Keys returns cache keys. the order is sorted by created.
4950
func (c *Cache[K, _]) Keys() []K {
51+
c.mu.RLock()
52+
defer c.mu.RUnlock()
53+
5054
ret := make([]K, 0, len(c.items))
5155
for key := range c.items {
5256
ret = append(ret, key)
5357
}
58+
sort.Slice(ret, func(i, j int) bool {
59+
i1 := c.items[ret[i]]
60+
i2 := c.items[ret[j]]
61+
return i1.CreatedAt.Before(i2.CreatedAt)
62+
})
5463
return ret
5564
}
65+
66+
// Delete deletes the item with provided key from the cache.
67+
func (c *Cache[K, V]) Delete(key K) {
68+
c.mu.Lock()
69+
defer c.mu.Unlock()
70+
delete(c.items, key)
71+
}
72+
73+
// Contains reports whether key is within cache.
74+
func (c *Cache[K, V]) Contains(key K) bool {
75+
c.mu.RLock()
76+
defer c.mu.RUnlock()
77+
item, ok := c.items[key]
78+
if !ok {
79+
return false
80+
}
81+
return !item.HasExpired()
82+
}

simple/simple_internal_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package simple
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
cache "github.com/Code-Hex/go-generics-cache"
8+
)
9+
10+
func TestContains(t *testing.T) {
11+
t.Run("without expiration", func(t *testing.T) {
12+
cache := NewCache[string, int]()
13+
cache.Set("foo", 1)
14+
cache.Set("bar", 2)
15+
cache.Set("baz", 3)
16+
for _, key := range []string{
17+
"foo",
18+
"bar",
19+
"baz",
20+
} {
21+
if !cache.Contains(key) {
22+
t.Errorf("not found: %s", key)
23+
}
24+
}
25+
if cache.Contains("not found") {
26+
t.Errorf("found")
27+
}
28+
})
29+
30+
t.Run("with expiration", func(t *testing.T) {
31+
c := NewCache[string, int]()
32+
key := "foo"
33+
exp := time.Hour
34+
c.Set(key, 1, cache.WithExpiration(exp))
35+
// modify directly
36+
item, ok := c.items[key]
37+
if !ok {
38+
t.Fatal("unexpected not found key")
39+
}
40+
item.CreatedAt = time.Now().Add(-2 * exp)
41+
42+
if c.Contains(key) {
43+
t.Errorf("found")
44+
}
45+
})
46+
}
47+
48+
func TestGet(t *testing.T) {
49+
c := NewCache[string, int]()
50+
key := "foo"
51+
exp := time.Hour
52+
c.Set(key, 1, cache.WithExpiration(exp))
53+
_, ok := c.Get(key)
54+
if !ok {
55+
t.Fatal("unexpected not found")
56+
}
57+
// modify directly
58+
item, ok := c.items[key]
59+
if !ok {
60+
t.Fatal("unexpected not found key")
61+
}
62+
item.CreatedAt = time.Now().Add(-2 * exp)
63+
_, ok2 := c.Get(key)
64+
if ok2 {
65+
t.Fatal("unexpected found (expired)")
66+
}
67+
}

0 commit comments

Comments
 (0)