@@ -3,6 +3,8 @@ package cache
3
3
import (
4
4
"context"
5
5
"errors"
6
+ "fmt"
7
+ "reflect"
6
8
"sync"
7
9
8
10
"github.com/eko/gocache/lib/v4/store"
@@ -55,56 +57,54 @@ func (c *LoadableCache[T]) setter() {
55
57
c .Set (context .Background (), item .key , item .value , item .options ... )
56
58
57
59
cacheKey := c .getCacheKey (item .key )
58
- c .singleFlight .Forget (cacheKey )
59
60
c .setCache .Delete (cacheKey )
60
61
}
61
62
}
62
63
63
64
// Get returns the object stored in cache if it exists
64
65
func (c * LoadableCache [T ]) Get (ctx context.Context , key any ) (T , error ) {
65
- var err error
66
-
67
- object , err := c .cache .Get (ctx , key )
68
- if err == nil {
69
- return object , err
70
- }
71
-
72
- // Unable to find in cache, try to load it from load function
73
66
cacheKey := c .getCacheKey (key )
74
- if v , ok := c .setCache .Load (cacheKey ); ok {
75
- return v .(T ), nil
76
- }
77
-
78
- zero := * new (T )
79
-
80
- rawLoadedResult , err , _ := c .singleFlight .Do (
67
+ if value , err , _ := c .singleFlight .Do (
81
68
cacheKey ,
82
69
func () (any , error ) {
83
- value , options , innerErr := c .loadFunc (ctx , key )
84
-
85
- return & loadableKeyValue [T ]{
86
- key : key ,
87
- value : value ,
88
- options : options ,
89
- }, innerErr
70
+ // try temporary-while-setter-works cache
71
+ if v , ok := c .setCache .Load (cacheKey ); ok {
72
+ return v , nil
73
+ }
74
+ // try main cache
75
+ if v , err := c .cache .Get (ctx , key ); err == nil {
76
+ return v , err
77
+ }
78
+ // Unable to find in cache, try to load it from load function
79
+ if value , options , err := c .loadFunc (ctx , key ); err == nil {
80
+
81
+ // cache locally until main cache is set
82
+ c .setCache .Store (cacheKey , value )
83
+
84
+ c .setChannel <- & loadableKeyValue [T ]{
85
+ key : key ,
86
+ value : value ,
87
+ options : options ,
88
+ }
89
+ return value , err
90
+ } else {
91
+ return * new (T ), err
92
+ }
90
93
},
91
- )
92
- if err != nil {
93
- return zero , err
94
- }
95
-
96
- loadedKeyValue , ok := rawLoadedResult .(* loadableKeyValue [T ])
97
- if ! ok {
94
+ ); err != nil {
95
+ return * new (T ), err
96
+ } else if value , ok := value .(T ); ok {
97
+ return value , err
98
+ } else {
99
+ zero := * new (T )
98
100
return zero , errors .New (
99
- "returned value can't be cast to *loadableKeyValue[T]" ,
101
+ fmt .Sprintf (
102
+ "type assertion failed: expected %s, got %s" ,
103
+ reflect .TypeOf (zero ),
104
+ reflect .TypeOf (value ),
105
+ ),
100
106
)
101
107
}
102
-
103
- // Then, put it back in cache
104
- c .setCache .Store (cacheKey , loadedKeyValue .value )
105
- c .setChannel <- loadedKeyValue
106
-
107
- return loadedKeyValue .value , err
108
108
}
109
109
110
110
// Set sets a value in available caches
0 commit comments