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)
Expand ▾ Collapse ▴

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

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

                    func (*FileBackend) Set

                    func (fb *FileBackend) Set(key string, entry *Entry) error

                      Set writes a cache entry

                      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

                              type HTTPLoader func(context.Context) (*http.Response, *Meta, error)

                                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) Flush

                                    func (*NullBackend) Flush() error

                                      Flush nothing

                                      func (*NullBackend) Get

                                      func (*NullBackend) Get(key string) (entry *Entry, found bool)

                                        Get nothing

                                        func (*NullBackend) Purge

                                        func (*NullBackend) Purge(key string) error

                                          Purge nothing

                                          func (*NullBackend) PurgeTags

                                          func (*NullBackend) PurgeTags(tags []string) error

                                            PurgeTags purges nothing

                                            func (*NullBackend) Set

                                            func (*NullBackend) Set(key string, entry *Entry) error

                                              Set 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

                                                    type StringLoader func() (string, *Meta, error)

                                                      StringLoader is used to load strings for singleflight cache loads