README
Cache module
The Cache module provides an easy interface to cache things in flamingo.
The basic concept is, that there is a so called "cache frontend" - that offers an interface to cache certain types, and a "cache backend" that takes care about storing(persiting) the cache entry.
Caching HTTP responses from APIs
A typical use case is, to cache responses from (slow) backends that you need to call.
First define an injection to get a HTTPFrontend cache injected:
MyApiClient struct {
Cache *cache.HTTPFrontend `inject:"myservice"`
}
We use annotation to be able to individually configure the requested Cache. So our binding may look like:
injector.Bind((*cache.HTTPFrontend)(nil)).AnnotatedWith("myservice").In(dingo.Singleton)
Then when you request your API you can wrap the result in the cache and provide a cache loader function. The HTTPFrontend Cache then makes sure that:
- If there is a cache hit - return it within the given "GraceTime" - and eventually do a new request if cache "LiveTime" is over.
- Requests for the same key are done in "single flight" if cache is empty meaning that even if there may be 1000 parallel requests only the first one will be executed against the backend service and the other wait for the result
Example:
loadData := func(ctx context.Context) (*http.Response, *cache.Meta, error) {
r, err := http.DefaultClient.Do(req.WithContext(ctx))
if err != nil {
return nil, nil, err
}
//cache semantic errors for certain time to avoid recalling the same request
if r.StatusCode == http.StatusNotFound {
return r, &cache.Meta{
Lifetime: 5 * time.Minute,
Gracetime: 300 * time.Second,
}, nil
}
//cache semantic errors for certain time to avoid recalling the same request
if r.StatusCode != http.StatusOK {
return r, &cache.Meta{
Lifetime: 10 * time.Second,
Gracetime: 30 * time.Second,
}, nil
}
return r, nil, nil
}
response, err := apiclient.Cache.Get(requestContext, u.String(), loadData)
Cache backends
Currently there are the following backends available:
- inMemoryCache (caches in memory - and therefore is a very fast cache)
- fileBackend (caches in filesystem )
- nullBackend (caches nothing)
Documentation
Index ¶
Constants ¶
Variables ¶
Functions ¶
Types ¶
type Backend ¶
type Backend interface { Get(key string) (entry *Entry, found bool) // Get a cache entry Set(key string, entry *Entry) error // Set a cache entry //Peek(key string) (entry *CacheEntry, found bool) // Peek for a cache entry, this should not trigger key-updates or weight/priorities to be changed Purge(key string) error PurgeTags(tags []string) error Flush() error }
Backend describes a cache backend, responsible for storing, flushing, setting and getting entries
func NewInMemoryCache ¶
func NewInMemoryCache() Backend
NewInMemoryCache creates a new lru TwoQueue backed cache backend
type Entry ¶
type Entry struct { Meta Meta Data interface{} }
Entry is a cached object with associated meta data
type FileBackend ¶
type FileBackend struct {
// contains filtered or unexported fields
}
FileBackend is a cache backend which saves the data in files
func NewFileBackend ¶
func NewFileBackend(baseDir string) *FileBackend
NewFileBackend returns a FileBackend operating in the given baseDir
func (*FileBackend) Flush ¶
func (*FileBackend) Flush() error
Flush is not supported by FileBackend and does nothing
func (*FileBackend) Get ¶
func (fb *FileBackend) Get(key string) (entry *Entry, found bool)
Get reads a cache entry
func (*FileBackend) Purge ¶
func (fb *FileBackend) Purge(key string) error
Purge deletes a cache entry
func (*FileBackend) PurgeTags ¶
func (*FileBackend) PurgeTags(tags []string) error
PurgeTags is not supported by FileBackend and does nothing
type HTTPFrontend ¶
type HTTPFrontend struct { singleflight.Group // contains filtered or unexported fields }
HTTPFrontend stores and caches http responses
func GetHTTPFrontendCacheWithNullBackend ¶
func GetHTTPFrontendCacheWithNullBackend() *HTTPFrontend
GetHTTPFrontendCacheWithNullBackend helper for tests
func (*HTTPFrontend) Get ¶
func (hf *HTTPFrontend) Get(ctx context.Context, key string, loader HTTPLoader) (*http.Response, error)
Get a http response, with tags and a loader the tags will be used when the entry is stored
func (*HTTPFrontend) Inject ¶
func (hf *HTTPFrontend) Inject(backend Backend, logger flamingo.Logger) *HTTPFrontend
Inject HTTPFrontend dependencies
type HTTPLoader ¶
HTTPLoader returns a response. it will be cached unless there is an error. this means 400/500 responses are cached too!
type Meta ¶
type Meta struct { Tags []string Lifetime, Gracetime time.Duration // contains filtered or unexported fields }
Meta describes life and gracetimes, as well as tags, for cache entries
type NullBackend ¶
type NullBackend struct{}
NullBackend does not store anything
func (*NullBackend) Get ¶
func (*NullBackend) Get(key string) (entry *Entry, found bool)
Get nothing
func (*NullBackend) PurgeTags ¶
func (*NullBackend) PurgeTags(tags []string) error
PurgeTags purges nothing
type StringFrontend ¶
type StringFrontend struct { singleflight.Group // contains filtered or unexported fields }
StringFrontend manages cache entries as strings
func (*StringFrontend) Get ¶
func (sf *StringFrontend) Get(key string, loader StringLoader) (string, error)
Get and load string cache entries
func (*StringFrontend) Inject ¶
func (sf *StringFrontend) Inject(backend Backend)
Inject StringFrontend dependencies
type StringLoader ¶
StringLoader is used to load strings for singleflight cache loads