github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/cache/store/memcache.go (about)

     1  package store
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/bradfitz/gomemcache/memcache"
    10  )
    11  
    12  const (
    13  	// MemcacheType represents the storage type as a string value
    14  	MemcacheType = "memcache"
    15  	// MemcacheTagPattern represents the tag pattern to be used as a key in specified storage
    16  	MemcacheTagPattern = "gocache_tag_%s"
    17  )
    18  
    19  // MemcacheStore is a store for Memcache
    20  type MemcacheStore struct {
    21  	// MemcacheClientInterface represents a bradfitz/gomemcache client
    22  	client  *memcache.Client
    23  	options *Options
    24  }
    25  
    26  // NewMemcache creates a new store to Memcache instance(s)
    27  func NewMemcache(client *memcache.Client, options *Options) *MemcacheStore {
    28  	if options == nil {
    29  		options = &Options{}
    30  	}
    31  
    32  	return &MemcacheStore{
    33  		client:  client,
    34  		options: options,
    35  	}
    36  }
    37  
    38  // Get returns data stored from a given key
    39  func (s *MemcacheStore) Get(key string) (interface{}, error) {
    40  	item, err := s.client.Get(key)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	if item == nil {
    45  		return nil, errors.New("unable to retrieve data from memcache")
    46  	}
    47  
    48  	return item.Value, err
    49  }
    50  
    51  // TTL returns a expiration time
    52  func (s *MemcacheStore) TTL(key string) (time.Duration, error) {
    53  	item, err := s.client.Get(key)
    54  	if err != nil {
    55  		return 0, err
    56  	}
    57  	if item == nil {
    58  		return 0, errors.New("unable to retrieve data from memcache")
    59  	}
    60  
    61  	return time.Second * time.Duration(item.Expiration), err
    62  }
    63  
    64  // Set defines data in Memcache for given key identifier
    65  func (s *MemcacheStore) Set(key string, value interface{}, options *Options) error {
    66  	if options == nil {
    67  		options = s.options
    68  	}
    69  
    70  	item := &memcache.Item{
    71  		Key:        key,
    72  		Value:      value.([]byte),
    73  		Expiration: int32(options.ExpirationValue().Seconds()),
    74  	}
    75  
    76  	err := s.client.Set(item)
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	if tags := options.TagsValue(); len(tags) > 0 {
    82  		s.setTags(key, tags)
    83  	}
    84  
    85  	return nil
    86  }
    87  
    88  func (s *MemcacheStore) setTags(key string, tags []string) {
    89  	for _, tag := range tags {
    90  		var tagKey = fmt.Sprintf(MemcacheTagPattern, tag)
    91  		var cacheKeys = []string{}
    92  
    93  		if result, err := s.Get(tagKey); err == nil {
    94  			if bytes, ok := result.([]byte); ok {
    95  				cacheKeys = strings.Split(string(bytes), ",")
    96  			}
    97  		}
    98  
    99  		var alreadyInserted = false
   100  		for _, cacheKey := range cacheKeys {
   101  			if cacheKey == key {
   102  				alreadyInserted = true
   103  				break
   104  			}
   105  		}
   106  
   107  		if !alreadyInserted {
   108  			cacheKeys = append(cacheKeys, key)
   109  		}
   110  
   111  		s.Set(tagKey, []byte(strings.Join(cacheKeys, ",")), &Options{
   112  			Expiration: 720 * time.Hour,
   113  		})
   114  	}
   115  }
   116  
   117  // Delete removes data from Memcache for given key identifier
   118  func (s *MemcacheStore) Delete(key string) error {
   119  	return s.client.Delete(key)
   120  }
   121  
   122  // Invalidate invalidates some cache data in Redis for given options
   123  func (s *MemcacheStore) Invalidate(options InvalidateOptions) error {
   124  	if tags := options.TagsValue(); len(tags) > 0 {
   125  		for _, tag := range tags {
   126  			var tagKey = fmt.Sprintf(MemcacheTagPattern, tag)
   127  			result, err := s.Get(tagKey)
   128  			if err != nil {
   129  				return nil
   130  			}
   131  
   132  			var cacheKeys = []string{}
   133  			if bytes, ok := result.([]byte); ok {
   134  				cacheKeys = strings.Split(string(bytes), ",")
   135  			}
   136  
   137  			for _, cacheKey := range cacheKeys {
   138  				s.Delete(cacheKey)
   139  			}
   140  		}
   141  	}
   142  
   143  	return nil
   144  }
   145  
   146  // Clear resets all data in the store
   147  func (s *MemcacheStore) Clear() error {
   148  	return s.client.FlushAll()
   149  }
   150  
   151  // GetType returns the store type
   152  func (s *MemcacheStore) GetType() string {
   153  	return MemcacheType
   154  }