-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathonce_cache.go
More file actions
60 lines (51 loc) · 1.95 KB
/
once_cache.go
File metadata and controls
60 lines (51 loc) · 1.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package once_cache
import (
"time"
"golang.org/x/sync/singleflight"
)
type SingleFunc func() (any, error)
type CatchErrorFunc func(cacheStore ICache, key string, err error) any
// IOnceCache is an interface that extends the ICache interface with a method for getting values with a single function.
type IOnceCache interface {
ICache
GetWithSingleFunc(key string, f SingleFunc, d time.Duration, catchError *CatchErrorFunc) (any, bool)
}
// OnceCache is a struct that implements the IOnceCache interface.
type OnceCache struct {
group *singleflight.Group
ICache
}
// GetWithSingleFunc retrieves a value associated with a key using a single function to generate the value.
// It ensures that the function is called only once for the same key within the specified time duration.
func (o *OnceCache) GetWithSingleFunc(key string, f SingleFunc, d time.Duration, catchError *CatchErrorFunc) (any, bool) {
// Attempt to get the value from the cache
value, ok := o.Get(key)
if !ok {
// If not found in the cache, use the singleflight.Group to ensure the function is called only once
// for the same key, even if multiple goroutines request the same key simultaneously.
defer o.group.Forget(key)
value, err, _ := o.group.Do(key, f)
if err != nil {
// If an error occurred while executing the function, handle the error and return false.
if catchError != nil {
catchErrorFunc := *catchError
catchErrorFunc(o, key, err)
}
// Even in case of an error, return the result from the cache if available.
return o.Get(key)
} else {
// If the function was successful, set the value in the cache and return true.
o.Set(key, value, d)
return value, true
}
}
// Return the value from the cache.
return value, ok
}
// NewOnceCache creates a new instance of OnceCache with the specified singleflight.Group and ICache.
func NewOnceCache(group *singleflight.Group, cacheStore ICache) IOnceCache {
return &OnceCache{
group: group,
ICache: cacheStore,
}
}