Skip to content

Instantly share code, notes, and snippets.

@seamusv
Created July 5, 2021 17:05
Show Gist options
  • Save seamusv/4c33981cb851dd3b09d90fb21bea28c1 to your computer and use it in GitHub Desktop.
Save seamusv/4c33981cb851dd3b09d90fb21bea28c1 to your computer and use it in GitHub Desktop.
Golang example of wrapping local cache and not have cache stampeding
package lcache
import (
"context"
"github.com/patrickmn/go-cache"
"golang.org/x/sync/singleflight"
"time"
)
type Cache struct {
c *cache.Cache
sf singleflight.Group
}
func NewCache(defaultExpiration, cleanupInterval time.Duration) *Cache {
return &Cache{
c: cache.New(defaultExpiration, cleanupInterval),
}
}
func (c *Cache) Get(ctx context.Context, key string, fn func(ctx context.Context) (interface{}, error)) (interface{}, error) {
res, err, _ := c.sf.Do(key, func() (interface{}, error) {
res, ok := c.c.Get(key)
if ok {
return res, nil
}
res, err := fn(ctx)
if err != nil {
return nil, err
}
c.c.Set(key, res, cache.DefaultExpiration)
return res, nil
})
return res, err
}
func (c *Cache) Delete(key string) {
c.c.Delete(key)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment