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

     1  package cache
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/angenalZZZ/gofunc/data/cache/store"
     8  )
     9  
    10  const (
    11  	// LoadableType represents the loadable cache type as a string value
    12  	LoadableType = "loadable"
    13  )
    14  
    15  type loadableKeyValue struct {
    16  	key   string
    17  	value interface{}
    18  }
    19  
    20  type loadFunction func(key interface{}) (interface{}, error)
    21  
    22  // LoadableCache represents a cache that uses a function to load data
    23  type LoadableCache struct {
    24  	loadFunc   loadFunction
    25  	cache      Interface
    26  	setChannel chan *loadableKeyValue
    27  }
    28  
    29  // NewLoadable create a new cache that uses a function to load data
    30  func NewLoadable(loadFunc loadFunction, cache Interface) *LoadableCache {
    31  	loadable := &LoadableCache{
    32  		loadFunc:   loadFunc,
    33  		cache:      cache,
    34  		setChannel: make(chan *loadableKeyValue, 10000),
    35  	}
    36  
    37  	go loadable.setter()
    38  
    39  	return loadable
    40  }
    41  
    42  func (c *LoadableCache) setter() {
    43  	for item := range c.setChannel {
    44  		_ = c.Set(item.key, item.value, nil)
    45  	}
    46  }
    47  
    48  // Get returns the object stored in cache if it exists
    49  func (c *LoadableCache) Get(key string) (object interface{}, err error) {
    50  	object, err = c.cache.Get(key)
    51  	if err == nil {
    52  		return
    53  	}
    54  
    55  	// Unable to find in cache, try to load it from load function
    56  	object, err = c.loadFunc(key)
    57  	if err != nil {
    58  		_ = fmt.Errorf("An error has occurred while trying to load item from load function: %v\n", err)
    59  		return
    60  	}
    61  
    62  	// Then, put it back in cache
    63  	c.setChannel <- &loadableKeyValue{key, object}
    64  	return
    65  }
    66  
    67  // Set sets a value in available caches
    68  func (c *LoadableCache) Set(key string, object interface{}, options *store.Options) error {
    69  	return c.cache.Set(key, object, options)
    70  }
    71  
    72  // TTL returns an expiration time
    73  func (c *LoadableCache) TTL(key string) (time.Duration, error) {
    74  	return c.cache.TTL(key)
    75  }
    76  
    77  // Delete removes a value from cache
    78  func (c *LoadableCache) Delete(key string) error {
    79  	return c.cache.Delete(key)
    80  }
    81  
    82  // Invalidate invalidates cache item from given options
    83  func (c *LoadableCache) Invalidate(options store.InvalidateOptions) error {
    84  	return c.cache.Invalidate(options)
    85  }
    86  
    87  // Clear resets all cache data
    88  func (c *LoadableCache) Clear() error {
    89  	return c.cache.Clear()
    90  }
    91  
    92  // GetType returns the cache type
    93  func (c *LoadableCache) GetType() string {
    94  	return LoadableType
    95  }