Skip to content

Commit 3c063dc

Browse files
committed
Make GetOrCreate return a bool indicating if the value was found in the cache
1 parent 0516096 commit 3c063dc

File tree

2 files changed

+14
-12
lines changed

2 files changed

+14
-12
lines changed

‎lazycache.go‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,20 @@ func (c *Cache[K, V]) Get(key K) (V, bool) {
8383
}
8484

8585
// GetOrCreate returns the value associated with key, or creates it if it doesn't.
86+
// It also returns a bool indicating if the value was found in the cache.
8687
// Note that create, the cache prime function, is called once and then not called again for a given key
8788
// unless the cache entry is evicted; it does not block other goroutines from calling GetOrCreate,
8889
// it is not called with the cache lock held.
8990
// Note that any error returned by create will be returned by GetOrCreate and repeated calls with the same key will
9091
// receive the same error.
91-
func (c *Cache[K, V]) GetOrCreate(key K, create func(key K) (V, error)) (V, error) {
92+
func (c *Cache[K, V]) GetOrCreate(key K, create func(key K) (V, error)) (V, bool, error) {
9293
c.mu.Lock()
9394
w := c.get(key)
9495
if w != nil {
9596
c.mu.Unlock()
9697
w.wait()
9798
// If w.ready is nil, we will repeat any error from the create function to concurrent callers.
98-
return w.value, w.err
99+
return w.value, true, w.err
99100
}
100101

101102
w = &valueWrapper[V]{
@@ -117,9 +118,9 @@ func (c *Cache[K, V]) GetOrCreate(key K, create func(key K) (V, error)) (V, erro
117118

118119
if err != nil {
119120
c.Delete(key)
120-
return c.zerov, err
121+
return c.zerov, false, err
121122
}
122-
return v, nil
123+
return v, false, nil
123124
}
124125

125126
// Resize changes the cache size and returns the number of entries evicted.

‎lazycache_test.go‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func TestDeleteFunc(t *testing.T) {
8787
go func() {
8888
defer wg.Done()
8989
for i := 10; i < 30; i++ {
90-
v, err := cache.GetOrCreate(i, func(key int) (any, error) {
90+
v, _, err := cache.GetOrCreate(i, func(key int) (any, error) {
9191
if key%2 == 0 {
9292
return nil, errors.New("failed")
9393
}
@@ -124,9 +124,10 @@ func TestGetOrCreate(t *testing.T) {
124124
return fmt.Sprintf("value-%d-%d", key, counter), nil
125125
}
126126
for i := 0; i < 3; i++ {
127-
res, err := cache.GetOrCreate(123456, create)
127+
res, found, err := cache.GetOrCreate(123456, create)
128128
c.Assert(err, qt.IsNil)
129129
c.Assert(res, qt.Equals, "value-123456-1")
130+
c.Assert(found, qt.Equals, i > 0)
130131
}
131132
v, found := cache.Get(123456)
132133
c.Assert(found, qt.IsTrue)
@@ -140,7 +141,7 @@ func TestGetOrCreateError(t *testing.T) {
140141
return nil, fmt.Errorf("failed")
141142
}
142143

143-
res, err := cache.GetOrCreate(123456, create)
144+
res, _, err := cache.GetOrCreate(123456, create)
144145
c.Assert(err, qt.ErrorMatches, "failed")
145146
c.Assert(res, qt.IsNil)
146147

@@ -171,7 +172,7 @@ func TestGetOrCreateConcurrent(t *testing.T) {
171172
go func() {
172173
defer wg.Done()
173174
for j := 0; j < 12; j++ {
174-
res, err := cache.GetOrCreate(i, create)
175+
res, _, err := cache.GetOrCreate(i, create)
175176
c.Assert(err, qt.IsNil)
176177
c.Assert(res, qt.Equals, expect)
177178
}
@@ -221,11 +222,11 @@ func TestGetOrCreateRecursive(t *testing.T) {
221222
key2++
222223
}
223224
shouldFail := key1%10 == 0
224-
v, err := cache.GetOrCreate(key1, func(key int) (any, error) {
225+
v, _, err := cache.GetOrCreate(key1, func(key int) (any, error) {
225226
if shouldFail {
226227
return nil, fmt.Errorf("failed")
227228
}
228-
v, err := cache.GetOrCreate(key2, func(key int) (any, error) {
229+
v, _, err := cache.GetOrCreate(key2, func(key int) (any, error) {
229230
return "inner", nil
230231
})
231232
c.Assert(err, qt.IsNil)
@@ -272,7 +273,7 @@ func BenchmarkGetOrCreateAndGet(b *testing.B) {
272273
b.Fatalf("got %v, want %v", v, i1)
273274
}
274275

275-
res2, err := cache.GetOrCreate(i2, func(key int) (any, error) {
276+
res2, _, err := cache.GetOrCreate(i2, func(key int) (any, error) {
276277
if i2%100 == 0 {
277278
// Simulate a slow create.
278279
time.Sleep(1 * time.Second)
@@ -312,7 +313,7 @@ func BenchmarkGetOrCreate(b *testing.B) {
312313
key := r.Intn(maxSize)
313314
mu.Unlock()
314315

315-
v, err := cache.GetOrCreate(key, func(int) (any, error) {
316+
v, _, err := cache.GetOrCreate(key, func(int) (any, error) {
316317
if key%100 == 0 {
317318
// Simulate a slow create.
318319
time.Sleep(1 * time.Second)

0 commit comments

Comments
 (0)