github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/util/cache/cache.go (about) 1 package cache 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "hash/fnv" 8 "time" 9 10 "github.com/tickoalcantara12/micro/v3/service/client" 11 "github.com/tickoalcantara12/micro/v3/service/context/metadata" 12 cache "github.com/patrickmn/go-cache" 13 ) 14 15 // New returns an initialised cache. 16 func New() *Cache { 17 return &Cache{ 18 cache: cache.New(cache.NoExpiration, 30*time.Second), 19 } 20 } 21 22 // Cache for responses 23 type Cache struct { 24 cache *cache.Cache 25 } 26 27 type Options struct { 28 // Expiry sets the cache expiry 29 Expiry time.Duration 30 } 31 32 // used to store the options in context 33 type optionsKey struct{} 34 35 // Get a response from the cache 36 func (c *Cache) Get(ctx context.Context, req client.Request) (interface{}, bool) { 37 return c.cache.Get(key(ctx, req)) 38 } 39 40 // Set a response in the cache 41 func (c *Cache) Set(ctx context.Context, req client.Request, rsp interface{}, expiry time.Duration) { 42 c.cache.Set(key(ctx, req), rsp, expiry) 43 } 44 45 // List the key value pairs in the cache 46 func (c *Cache) List() map[string]string { 47 items := c.cache.Items() 48 49 rsp := make(map[string]string, len(items)) 50 for k, v := range items { 51 bytes, _ := json.Marshal(v.Object) 52 rsp[k] = string(bytes) 53 } 54 55 return rsp 56 } 57 58 // key returns a hash for the context and request 59 func key(ctx context.Context, req client.Request) string { 60 ns, _ := metadata.Get(ctx, "Micro-Namespace") 61 62 bytes, _ := json.Marshal(map[string]interface{}{ 63 "namespace": ns, 64 "request": map[string]interface{}{ 65 "service": req.Service(), 66 "endpoint": req.Endpoint(), 67 "method": req.Method(), 68 "body": req.Body(), 69 }, 70 }) 71 72 h := fnv.New64() 73 h.Write(bytes) 74 return fmt.Sprintf("%x", h.Sum(nil)) 75 } 76 77 func SetOptions(ctx context.Context, opts *Options) context.Context { 78 if ctx == nil { 79 ctx = context.Background() 80 } 81 return context.WithValue(ctx, optionsKey{}, opts) 82 } 83 84 func GetOptions(ctx context.Context) (*Options, bool) { 85 if ctx == nil { 86 return nil, false 87 } 88 opts, ok := ctx.Value(optionsKey{}).(*Options) 89 return opts, ok 90 } 91 92 func CallOption(opts *Options) client.CallOption { 93 return func(o *client.CallOptions) { 94 if o.Context == nil { 95 o.Context = context.Background() 96 } 97 o.Context = SetOptions(o.Context, opts) 98 } 99 } 100 101 func CallExpiry(t time.Duration) client.CallOption { 102 return CallOption(&Options{ 103 Expiry: t, 104 }) 105 }