Added custom cache client for much easier cache operations.
This commit is contained in:
parent
09c6df7f52
commit
e0a65ca007
8 changed files with 451 additions and 64 deletions
204
services/cache.go
Normal file
204
services/cache.go
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/eko/gocache/v2/cache"
|
||||
"github.com/eko/gocache/v2/marshaler"
|
||||
"github.com/eko/gocache/v2/store"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/mikestefanello/pagoda/config"
|
||||
)
|
||||
|
||||
type (
|
||||
// CacheClient is the client that allows you to interact with the cache
|
||||
CacheClient struct {
|
||||
// Client stores the client to the underlying cache service
|
||||
Client *redis.Client
|
||||
|
||||
// cache stores the cache interface
|
||||
cache *cache.Cache
|
||||
}
|
||||
|
||||
// cacheSet handles chaining a set operation
|
||||
cacheSet struct {
|
||||
client *CacheClient
|
||||
key string
|
||||
group string
|
||||
data interface{}
|
||||
expiration time.Duration
|
||||
tags []string
|
||||
}
|
||||
|
||||
// cacheGet handles chaining a get operation
|
||||
cacheGet struct {
|
||||
client *CacheClient
|
||||
key string
|
||||
group string
|
||||
dataType interface{}
|
||||
}
|
||||
|
||||
// cacheFlush handles chaining a flush operation
|
||||
cacheFlush struct {
|
||||
client *CacheClient
|
||||
key string
|
||||
group string
|
||||
tags []string
|
||||
}
|
||||
)
|
||||
|
||||
// NewCacheClient creates a new cache client
|
||||
func NewCacheClient(cfg config.CacheConfig) (*CacheClient, error) {
|
||||
c := &CacheClient{}
|
||||
c.Client = redis.NewClient(&redis.Options{
|
||||
Addr: fmt.Sprintf("%s:%d", cfg.Hostname, cfg.Port),
|
||||
Password: cfg.Password,
|
||||
})
|
||||
if _, err := c.Client.Ping(context.Background()).Result(); err != nil {
|
||||
return c, err
|
||||
}
|
||||
|
||||
cacheStore := store.NewRedis(c.Client, nil)
|
||||
c.cache = cache.New(cacheStore)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Close closes the connection to the cache
|
||||
func (c *CacheClient) Close() error {
|
||||
return c.Client.Close()
|
||||
}
|
||||
|
||||
// Set creates a cache set operation
|
||||
func (c *CacheClient) Set() *cacheSet {
|
||||
return &cacheSet{
|
||||
client: c,
|
||||
}
|
||||
}
|
||||
|
||||
// Get creates a cache get operation
|
||||
func (c *CacheClient) Get() *cacheGet {
|
||||
return &cacheGet{
|
||||
client: c,
|
||||
}
|
||||
}
|
||||
|
||||
// Flush creates a cache flush operation
|
||||
func (c *CacheClient) Flush() *cacheFlush {
|
||||
return &cacheFlush{
|
||||
client: c,
|
||||
}
|
||||
}
|
||||
|
||||
// cacheKey formats a cache key with an optional group
|
||||
func (c *CacheClient) cacheKey(group, key string) string {
|
||||
if group != "" {
|
||||
return fmt.Sprintf("%s::%s", group, key)
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
// Key sets the cache key
|
||||
func (c *cacheSet) Key(key string) *cacheSet {
|
||||
c.key = key
|
||||
return c
|
||||
}
|
||||
|
||||
// Group sets the cache group
|
||||
func (c *cacheSet) Group(group string) *cacheSet {
|
||||
c.group = group
|
||||
return c
|
||||
}
|
||||
|
||||
// Data sets the data to cache
|
||||
func (c *cacheSet) Data(data interface{}) *cacheSet {
|
||||
c.data = data
|
||||
return c
|
||||
}
|
||||
|
||||
// Expiration sets the expiration duration of the cached data
|
||||
func (c *cacheSet) Expiration(expiration time.Duration) *cacheSet {
|
||||
c.expiration = expiration
|
||||
return c
|
||||
}
|
||||
|
||||
// Tags sets the cache tags
|
||||
func (c *cacheSet) Tags(tags []string) *cacheSet {
|
||||
c.tags = tags
|
||||
return c
|
||||
}
|
||||
|
||||
// Save saves the data in the cache
|
||||
func (c *cacheSet) Save(ctx context.Context) error {
|
||||
opts := &store.Options{
|
||||
Expiration: c.expiration,
|
||||
Tags: c.tags,
|
||||
}
|
||||
|
||||
return marshaler.
|
||||
New(c.client.cache).
|
||||
Set(ctx, c.client.cacheKey(c.group, c.key), c.data, opts)
|
||||
}
|
||||
|
||||
// Key sets the cache key
|
||||
func (c *cacheGet) Key(key string) *cacheGet {
|
||||
c.key = key
|
||||
return c
|
||||
}
|
||||
|
||||
// Group sets the cache group
|
||||
func (c *cacheGet) Group(group string) *cacheGet {
|
||||
c.group = group
|
||||
return c
|
||||
}
|
||||
|
||||
// Type sets the expected Go type of the data being retrieved from the cache
|
||||
func (c *cacheGet) Type(expectedType interface{}) *cacheGet {
|
||||
c.dataType = expectedType
|
||||
return c
|
||||
}
|
||||
|
||||
// Fetch fetches the data from the cache
|
||||
func (c *cacheGet) Fetch(ctx context.Context) (interface{}, error) {
|
||||
return marshaler.New(c.client.cache).Get(
|
||||
ctx,
|
||||
c.client.cacheKey(c.group, c.key),
|
||||
c.dataType,
|
||||
)
|
||||
}
|
||||
|
||||
// Key sets the cache key
|
||||
func (c *cacheFlush) Key(key string) *cacheFlush {
|
||||
c.key = key
|
||||
return c
|
||||
}
|
||||
|
||||
// Group sets the cache group
|
||||
func (c *cacheFlush) Group(group string) *cacheFlush {
|
||||
c.group = group
|
||||
return c
|
||||
}
|
||||
|
||||
// Tags sets the cache tags
|
||||
func (c *cacheFlush) Tags(tags []string) *cacheFlush {
|
||||
c.tags = tags
|
||||
return c
|
||||
}
|
||||
|
||||
// Exec flushes the data from the cache
|
||||
func (c *cacheFlush) Exec(ctx context.Context) error {
|
||||
if len(c.tags) > 0 {
|
||||
if err := c.client.cache.Invalidate(ctx, store.InvalidateOptions{
|
||||
Tags: c.tags,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if c.key != "" {
|
||||
return c.client.cache.Delete(ctx, c.client.cacheKey(c.group, c.key))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue