Skip to content

Commit d2a0648

Browse files
author
Gleb Vasylenko
committed
Add GetWithFallback method to fallback non existent or expired keys
1 parent 77bbae4 commit d2a0648

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

bigcache.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,32 @@ func (c *BigCache) Get(key string) ([]byte, error) {
123123
return shard.get(key, hashedKey)
124124
}
125125

126+
// GetWithFallback reads entry for the key and if it is not exists
127+
// tries to call second argument callback function to resolve actual value,
128+
// after tries to save it as new cached value for the key and returns it as result.
129+
func (c *BigCache) GetWithFallback(key string, fallbackFn func() ([]byte, error)) ([]byte, error) {
130+
entry, err := c.Get(key)
131+
if err == nil {
132+
return entry, nil
133+
}
134+
135+
if err != ErrEntryNotFound {
136+
return nil, err
137+
}
138+
139+
entry, err = fallbackFn()
140+
if err != nil {
141+
return nil, err
142+
}
143+
144+
err = c.Set(key, entry)
145+
if err != nil {
146+
return nil, err
147+
}
148+
149+
return entry, nil
150+
}
151+
126152
// GetWithInfo reads entry for the key with Response info.
127153
// It returns an ErrEntryNotFound when
128154
// no entry exists for the given key.

bigcache_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package bigcache
22

33
import (
44
"bytes"
5+
"errors"
56
"fmt"
67
"math"
78
"math/rand"
@@ -28,6 +29,39 @@ func TestWriteAndGetOnCache(t *testing.T) {
2829
assertEqual(t, value, cachedValue)
2930
}
3031

32+
func TestGetWithFallbackOnCache(t *testing.T) {
33+
t.Parallel()
34+
35+
// given
36+
cache, _ := NewBigCache(DefaultConfig(5 * time.Second))
37+
value := []byte("value")
38+
39+
// when
40+
cachedValue, err := cache.GetWithFallback("key", func() ([]byte, error) {
41+
return value, nil
42+
})
43+
44+
// then
45+
noError(t, err)
46+
assertEqual(t, value, cachedValue)
47+
}
48+
49+
func TestGetWithFallbackOnCacheWithError(t *testing.T) {
50+
t.Parallel()
51+
52+
// given
53+
cache, _ := NewBigCache(DefaultConfig(5 * time.Second))
54+
errStub := errors.New("some error")
55+
56+
// when
57+
_, err := cache.GetWithFallback("key", func() ([]byte, error) {
58+
return nil, errStub
59+
})
60+
61+
// then
62+
assertEqual(t, errStub, err)
63+
}
64+
3165
func TestAppendAndGetOnCache(t *testing.T) {
3266
t.Parallel()
3367

examples_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ func Example() {
1818
// Output: value
1919
}
2020

21+
func Example_getWithFallback() {
22+
cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))
23+
24+
entry, _ := cache.GetWithFallback("my-unique-key", func() ([]byte, error) {
25+
/* Some amount of code for resolving value... */
26+
return []byte("value"), nil
27+
})
28+
29+
fmt.Println(string(entry))
30+
// Output: value
31+
}
32+
2133
func Example_custom() {
2234
// When cache load can be predicted in advance then it is better to use custom initialization
2335
// because additional memory allocation can be avoided in that way.

0 commit comments

Comments
 (0)