@@ -12,6 +12,7 @@ import (
1212 t "github.com/darkweak/souin/configurationtypes"
1313 "github.com/darkweak/souin/pkg/rfc"
1414 "github.com/darkweak/souin/pkg/storage/types"
15+ "github.com/google/uuid"
1516 "github.com/imdario/mergo"
1617 "github.com/nutsdb/nutsdb"
1718 "go.uber.org/zap"
@@ -179,29 +180,10 @@ func (provider *NutsMemcached) MapKeys(prefix string) map[string]string {
179180
180181// Get method returns the populated response if exists, empty response then
181182func (provider * NutsMemcached ) Get (key string ) (item []byte ) {
182- // get from nuts
183- keyFound := false
184- {
185- _ = provider .DB .View (func (tx * nutsdb.Tx ) error {
186- i , e := tx .Get (bucket , []byte (key ))
187- if i != nil {
188- // Value is stored in memcached
189- //item = i.Value
190- keyFound = true
191- }
192- return e
193- })
194- }
195-
196- // get from memcached
197- if keyFound {
198- // Reminder: the key must be at most 250 bytes in length
199- //fmt.Println("memcached GET", key)
200- i , e := provider .memcacheClient .Get (key )
201- if e == nil && i != nil {
202- item = i .Value
203- }
183+ memcachedKey , _ := provider .getFromNuts (key )
204184
185+ if memcachedKey != "" {
186+ item , _ = provider .getFromMemcached (memcachedKey )
205187 }
206188
207189 return
@@ -220,14 +202,14 @@ func (provider *NutsMemcached) Prefix(key string, req *http.Request, validator *
220202 for _ , entry := range entries {
221203 if varyVoter (key , req , string (entry .Key )) {
222204 // TODO: improve this
223- // store header only in nuts and avoid query to memcached on each vary
205+ // Store only response header in nuts and avoid query to memcached on each vary
224206 // E.g, rfc.ValidateETag on NutsDB header value, retrieve response body later from memcached.
225207
226208 // Reminder: the key must be at most 250 bytes in length
227209 //fmt.Println("memcached PREFIX", key, "GET", string(entry.Key))
228- i , e := provider .memcacheClient . Get (string (entry .Key ))
229- if e == nil && i != nil {
230- res , err := http .ReadResponse (bufio .NewReader (bytes .NewBuffer (i . Value )), req )
210+ i , e := provider .getFromMemcached (string (entry .Value ))
211+ if e == nil {
212+ res , err := http .ReadResponse (bufio .NewReader (bytes .NewBuffer (i )), req )
231213 if err == nil {
232214 rfc .ValidateETag (res , validator )
233215 if validator .Matched {
@@ -257,12 +239,14 @@ func (provider *NutsMemcached) Set(key string, value []byte, url t.URL, ttl time
257239 if ttl == 0 {
258240 ttl = url .TTL .Duration
259241 }
242+ memcachedKey := uuid .New ().String ()
260243
261244 // set to nuts (normal TTL)
262245 {
263246 err := provider .DB .Update (func (tx * nutsdb.Tx ) error {
264- // No value is stored, value is stored in memcached
265- return tx .Put (bucket , []byte (key ), []byte {}, uint32 (ttl .Seconds ()))
247+
248+ // key: cache-key, value: memcached-key
249+ return tx .Put (bucket , []byte (key ), []byte (memcachedKey ), uint32 (ttl .Seconds ()))
266250 })
267251
268252 if err != nil {
@@ -275,8 +259,8 @@ func (provider *NutsMemcached) Set(key string, value []byte, url t.URL, ttl time
275259 staleTtl := int32 ((provider .stale + ttl ).Seconds ())
276260 {
277261 err := provider .DB .Update (func (tx * nutsdb.Tx ) error {
278- // No value is stored , value is stored in memcached
279- return tx .Put (bucket , []byte (StalePrefix + key ), []byte {} , uint32 (staleTtl ))
262+ // key: "STALE_" + cache-key , value: memcached-key
263+ return tx .Put (bucket , []byte (StalePrefix + key ), []byte ( memcachedKey ) , uint32 (staleTtl ))
280264 })
281265
282266 if err != nil {
@@ -285,38 +269,36 @@ func (provider *NutsMemcached) Set(key string, value []byte, url t.URL, ttl time
285269 }
286270
287271 // set to memcached with stale TTL
288- {
289- // Reminder: the key must be at most 250 bytes in length
290- //fmt.Println("memcached SET", key)
291- err := provider .memcacheClient .Set (
292- & memcache.Item {
293- Key : key ,
294- Value : value ,
295- Expiration : staleTtl ,
296- },
297- )
298- if err != nil {
299- provider .logger .Sugar ().Errorf ("Impossible to set value into Memcached, %v" , err )
300- }
301- }
272+ _ = provider .setToMemcached (memcachedKey , value , staleTtl )
302273
303274 return nil
304275}
305276
306277// Delete method will delete the response in Nuts provider if exists corresponding to key param
307278func (provider * NutsMemcached ) Delete (key string ) {
279+ memcachedKey , _ := provider .getFromNuts (key )
280+
281+ // delete from memcached
282+ if memcachedKey != "" {
283+ _ = provider .delFromMemcached (memcachedKey )
284+ }
285+
286+ // delete from nuts
308287 _ = provider .DB .Update (func (tx * nutsdb.Tx ) error {
309288 return tx .Delete (bucket , []byte (key ))
310289 })
311290}
312291
313292// DeleteMany method will delete the responses in Nuts provider if exists corresponding to the regex key param
314- func (provider * NutsMemcached ) DeleteMany (key string ) {
293+ func (provider * NutsMemcached ) DeleteMany (keyReg string ) {
315294 _ = provider .DB .Update (func (tx * nutsdb.Tx ) error {
316- if entries , err := tx .PrefixSearchScan (bucket , []byte ("" ), key , 0 , nutsLimit ); err != nil {
295+ if entries , err := tx .PrefixSearchScan (bucket , []byte ("" ), keyReg , 0 , nutsLimit ); err != nil {
317296 return err
318297 } else {
319298 for _ , entry := range entries {
299+ // delete from memcached
300+ _ = provider .delFromMemcached (string (entry .Value ))
301+ // delete from nuts
320302 _ = tx .Delete (bucket , entry .Key )
321303 }
322304 }
@@ -335,3 +317,47 @@ func (provider *NutsMemcached) Reset() error {
335317 return tx .DeleteBucket (1 , bucket )
336318 })
337319}
320+
321+ func (provider * NutsMemcached ) getFromNuts (nutsKey string ) (memcachedKey string , err error ) {
322+ err = provider .DB .View (func (tx * nutsdb.Tx ) error {
323+ i , e := tx .Get (bucket , []byte (nutsKey ))
324+ if i != nil {
325+ memcachedKey = string (i .Value )
326+ }
327+ return e
328+ })
329+ return
330+ }
331+
332+ // Reminder: the memcachedKey must be at most 250 bytes in length
333+ func (provider * NutsMemcached ) setToMemcached (memcachedKey string , value []byte , ttl int32 ) (err error ) {
334+ //fmt.Println("memcached SET", key)
335+ err = provider .memcacheClient .Set (
336+ & memcache.Item {
337+ Key : memcachedKey ,
338+ Value : value ,
339+ Expiration : ttl ,
340+ },
341+ )
342+ if err != nil {
343+ provider .logger .Sugar ().Errorf ("Failed to set into memcached, %v" , err )
344+ }
345+ return
346+ }
347+
348+ // Reminder: the memcachedKey must be at most 250 bytes in length
349+ func (provider * NutsMemcached ) getFromMemcached (memcachedKey string ) (value []byte , err error ) {
350+ //fmt.Println("memcached GET", key)
351+ i , err := provider .memcacheClient .Get (memcachedKey )
352+ if err == nil && i != nil {
353+ value = i .Value
354+ } else {
355+ provider .logger .Sugar ().Errorf ("Failed to get from memcached, %v" , err )
356+ }
357+ return
358+ }
359+
360+ func (provider * NutsMemcached ) delFromMemcached (memcachedKey string ) (err error ) {
361+ err = provider .memcacheClient .Delete (memcachedKey )
362+ return
363+ }
0 commit comments