viney-shih/go-cache

View on GitHub
interface.go

Summary

Maintainability
A
0 mins
Test Coverage
package cache

import (
    "context"
    "errors"
    "time"
)

var (
    // ErrCacheMiss indicates the key is missing
    ErrCacheMiss = errors.New("cache key is missing")
    // ErrPfxNotRegistered means the prefix is not registered
    ErrPfxNotRegistered = errors.New("prefix not registered")
    // ErrMGetterResponseLengthInvalid means mgetter return a slice with wrong length,
    // the response length should be equal to the getterParams length
    ErrMGetterResponseLengthInvalid = errors.New("wrong mgetter response length")
    // ErrMGetterResponseNotSlice means mgetter's response type is not slice
    ErrMGetterResponseNotSlice = errors.New("mgetter response not a slice")
    // ErrResultIndexInvalid means the index for Result.Get is out of range
    ErrResultIndexInvalid = errors.New("index out of range")
)

// OneTimeGetterFunc should be provided as a parameter in GetByFunc()
type OneTimeGetterFunc func() (interface{}, error)

// MGetterFunc should response a slice of elements which has 1-1 mapping with the provided keys
type MGetterFunc func(keys ...string) (interface{}, error)

// Type decides which components are used in multi-layer cache structure
type Type int32

// All kinds of cache component type
const (
    // NoneType
    NoneType Type = iota
    // SharedCacheType means shared caching. It ensures that different application instances see the same view of cached data.
    // The famous frameworks are Redis, Memcached, ... (Ref: https://en.wikipedia.org/wiki/Distributed_cache)
    SharedCacheType
    // LocalCacheType means private caching in a single application instance, and the most basic type of cache is an in-memory store.
    // It's held in the address space of a single process and accessed directly by the code that runs in that process.
    // Due to the limited space of memory, we need to consider the efficient cache eviction policy to keep the most important
    // items in it. (Ref: https://en.wikipedia.org/wiki/Cache_replacement_policies)
    LocalCacheType
)

// Factory is initialized in the main.go, and used to generate the Cache for each business logic
type Factory interface {
    NewCache(settings []Setting) Cache
    Close()
}

// NewFactory returns the Factory initialized in the main.go.
func NewFactory(sharedCache Adapter, localCache Adapter, options ...FactoryOptions) Factory {
    return newFactory(sharedCache, localCache, options...)
}

// Cache is generated by Factory based on the need specified in the Setting slice.
// Use the following methods to create key/value store.
type Cache interface {
    // GetByFunc returns a value in the cache. It also follows up the Cache-Aside pattern.
    // When cache-miss happened, it relaods the value by the getter, and fill in the cache again.
    GetByFunc(context context.Context, prefix, key string, container interface{}, getter OneTimeGetterFunc) error
    // Get returns a value in the cache.
    // When cache-miss happened, it relaods the value by MGetter specified in the setting if possible.
    // Or returns the error of ErrCacheMiss.
    Get(context context.Context, prefix, key string, container interface{}) error
    // MGet returns values in the cache with the interface Result.
    // When cache-miss happened, it relaods values by MGetter specified in the setting if possible.
    // Or returns the error of ErrCacheMiss.
    MGet(context context.Context, prefix string, keys ...string) (Result, error)
    // Del remove keys in the cache
    Del(context context.Context, prefix string, keys ...string) error
    // Set sets up a value into the cache.
    Set(context context.Context, prefix string, key string, value interface{}) error
    // MSet sets up values into the cache.
    MSet(context context.Context, prefix string, keyValues map[string]interface{}) error
}

// Setting provides a relation between Prefix and detailed Attributes.
// One Setting stands for a one group of a cache, and it use Prefix stands for the unique id.
// In other words, a group of a cache has it's own Attributes like TTL.
type Setting struct {
    // Prefix is unique id for a group of the cache.
    Prefix string
    // CacheAttributes includes all detail attributes.
    CacheAttributes map[Type]Attribute
    // MGetter should be provided when using Cache-Aside pattern
    MGetter MGetterFunc
    // MarshalFunc specified the marshal function
    // Needs to consider with unmarshal function at the same time.
    MarshalFunc MarshalFunc
    // UnmarshalFunc specified the unmarshal function
    // Needs to consider with marshal function at the same time.
    UnmarshalFunc UnmarshalFunc
}

// Attribute specified details. For example, you need to indicate the TTL for each key to expire.
type Attribute struct {
    TTL time.Duration
}

// Result is the return values from MGet(). You need a for loop to parse whole values.
type Result interface {
    Len() int
    Get(ctx context.Context, index int, container interface{}) error
}

// ClearPrefix is only used by unit tests that clean up registered prefix, otherwise
// duplicated prefix registration panic might occur due to multiple tests.
func ClearPrefix() {
    usedPrefixs = map[string]struct{}{}
}

// Register registers customized parameters in the package.
func Register(packageKey string) {
    registerKey(packageKey)
}