score.kvcache

Introduction

This module allows storing python objects in key-value storages. It can be used, for example, to cache frequently used data to avoid calling APIs too often or to avoid exceeding the number of allowed calls to a service. It should not be used to persist data, since it cannot guarantee that data is retained, even if the specified expiration is not reached. Where and how long the data is stored depends on the configurable backend.

How it works

This module uses configurable cache containers to store values with different lifetimes and generators. A cache value generator is a function, that needs to be configured or registered with the container. The cache container will invoke this cache value generator to obtain the matching cache value for the requested key.

If you want to configure your generator, have a look at the Configuration. The registration of a cache value generator can be done by calling the container’s ConfiguredKvCacheModule.register_generator() method:

import score.kvcache

def greeting_generator(name):
    print('Generating the value for key "%s".' % name)
    return 'Hello %s!' % name

kvcache = score.kvcache.init({
    'backend.variable': 'score.kvcache.backend.VariableCache',
    'container.greeting.backend': 'variable',
})

kvcache.register_generator('greeting', greeting_generator)

print(kvcache['greeting']['Peter'])
print(kvcache['greeting']['Peter'])
print(kvcache['greeting']['William'])

The output will be:

Generating the value for key "Peter".
Hello Peter!
Hello Peter!
Generating the value for key "William".
Hello William!

In this scenario, the configured kvcache will operate only on one container called greeting. The container is associated with the backend called variable, which is a dummy backend storing values in a python dict.

The first time the container is accessed with the key Peter, the container will consult its backend and catch a NotFound Exception. Since it was not possible to retrieve the value from cache, it will invoke the registered generator to create the desired value (“Hello Peter!”).

The backend is then instructed to store the value, having it available the next time the container is requested to retrieve the exact same key.

If we had chosen a more elaborate backend, we could have even configured an expiration time for the values in our container.

Configuration

score.kvcache.init(confdict)[source]

Initializes this module according to our module initialization guidelines with the following configuration keys:

container

The cache container configuration. A container defines a name, a backend and optionally a generator and an expire. The configuration key for a container starts with container followed by the name and the configuration keys for the container.

For example, the following configuration:

container.greeter.backend = score.kvcache.backend.FileCache
container.greeter.backend.path = /tmp/greeter.sqlite3
container.greeter.generator = dotted.path.to.greeting_generator
container.greeter.expire = 1m

The Backend config will be passed to score.init.init_object(). Have a look at the configurable backend’s constructor parameters for further information about the backend’s configurable keys.

To make life easier for a huge set of container configurations, we serve the possibility to configure backend aliases that will replace the container’s backend config if the name matches.

For example:

backend.example_filecache = score.kvcache.backend.FileCache
backend.example_filecache.path = /tmp/filecache.sqlite3
container.greeter.backend = example_filecache
container.greeter.generator = dotted.path.to.greeting_generator
container.greeter.expire = 1m
container.counter.backend = example_filecache
container.counter.generator = dotted.path.to.counting_generator
container.counter.expire = 30 seconds
class score.kvcache.ConfiguredKvCacheModule(containers)[source]

This module’s configuration object.

containers

A dictionary containing all configured CacheContainer. The keys of the dictionary represent the container names.

__getitem__(container)[source]

Gets a Cachecontainer for given name.

register_generator(container, generator)[source]

Registers the generator to call if the cache is invalid.

create_container(container, *, exist_ok=False)[source]

Creates a container with given name and a VariableCache and adds it to the configured containers. dictionary. Will raise a ContainerAlreadyConfigured if exist_ok=False and the container is already configured.

class score.kvcache.CacheContainer(name, backend, expire=None)[source]

A cache container to wrap key-value pairs.

name

The container name.

backend

The container Backend.

expire

The expire parsed by score.init.parse_time_interval(). May be None.

generator

The generator registered by ConfiguredKvCacheModule.register_generator(). The argument of the generator represents the key of the cache item.

__delitem__(key)[source]

Invalidates a value for given key.

__getitem__(key)[source]

Gets a value for given key and takes care of not found cache items.

__setitem__(key, value)[source]

Explicitly sets a value for given key ignoring validity.

class score.kvcache.backend.Backend[source]
store(container, key, value, expire=None)[source]

Stores a value for given container name and key with given expire.

retrieve(container, key)[source]

Retrieves a value for given container and key and raises an NotFound if the value is invalid.

invalidate(container, key)[source]

Invalidates a value for given container and key.

class score.kvcache.NotFound[source]

Thrown if cache is invalid (either expired or not available).

class score.kvcache.ContainerAlreadyConfigured[source]

Thrown while trying to create a cache container that already exists.

Ready-to-use Backends

class score.kvcache.backend.VariableCache[source]

This backend implementation caches values in a variable. Note, that the expire is restricted to the process’s lifetime.

class score.kvcache.backend.FileCache(path)[source]

This backend implementation caches values in a sqlite3 database with given path.

path

The path to the sqlite3 file.

class score.kvcache.backend.SQLAlchemyCache(**confdict)[source]

This backend implementation caches values in a database supported by sqlalchemy.

confdict

The sqlalchemy configuration dictionary. All configuration keys must start with sqlalchemy. The dictionary will be passed to sqlalchemy.engine_from_config(), which in turn calls sqlalchemy.create_engine() with these configuration values as keyword arguments. Usually the following is sufficient:

sqlalchemy.url = postgresql://dbuser@localhost/dbname