Customisation¶
The following functions, classes and delegates allow customisation of different
details of how Hermes
instance works.
Custom cache keys¶
|
Wrap the callable in a cache-point instance. |
In rare cases like metaprogramming Mangler.nameEntry
cannot determine
correct and unique cache key. In such cases a function to compute the cache key
name can be passed to the decorator:
cache = hermes.Hermes(hermes.backend.redis.Backend)
@cache(key = lambda fn, a: f'{repr(fn).rsplit(" at 0x", 1)[0]}:{a}')
@magic_metaprogramming_sauce
def fn(a):
return a + 1
Dynamic TTL¶
|
Wrap the callable in a cache-point instance. |
Usually TTL of cache entries is a fixed number (of seconds). However, to
support custom intervals, like time until midnight, or caching a class of
return values of a cached function longer, ttl
argument of the decorator
can be a callable:
cache = hermes.Hermes(hermes.backend.redis.Backend)
@cache(ttl = lambda ret_val, get_foo, id: 7200 if ret_val.is_longlived else 3600)
def get_foo(id):
return foo_repo.get(id)
Hermes.ttl
can be set to a callable too, hence TTL can be managed
centrally, if needed.
Hash algorithm¶
|
Key manager responsible for creating keys, hashing and serialisation. |
class CustomMangler(hermes.Mangler):
def hash(self, value):
return str(hash(value))
cache = hermes.Hermes(
hermes.backend.redis.Backend, mangler = CustomMangler()
)
Serialisation¶
|
Serialisation delegate. |
cache = hermes.Hermes(hermes.backend.redis.Backend)
# use another serialisation algorithm
cache.mangler.serialiser = hermes.Serialiser(
msgpack.dumps, lambda b: msgpack.loads(b, strict_map_key = False)
)
Сompression¶
|
Compression delegate. |
cache = hermes.Hermes(hermes.backend.redis.Backend)
# disable compression
cache.mangler.compressor = None
# use another compression algorithm
cache.mangler.compressor = hermes.Compressor(
snappy.compress, snappy.decompress, snappy.UncompressError, 32
)
Tolerating cache server errors¶
|
Cache-point wrapper for callables and descriptors. |
|
Cache-point wrapper for coroutine functions. |
This can be used to ignore backend errors when the cache server is down by falling back to the cached callable directly.
class CustomCached(hermes.Cached):
def __call__(self, *args, **kwargs):
try:
return super().__call__(*args, **kwargs)
except redis.RedisError:
return self._callable(*args, **kwargs)
def cachedfactory(frontend: hermes.Hermes, fn, **kwargs) -> hermes.Cached:
if callable(fn) or inspect.ismethoddescriptor(fn):
return CustomCached(frontend, fn, **kwargs)
else:
raise HermesError(
'First positional argument must be a callable or method descriptor'
)
cache = hermes.Hermes(
hermes.backend.redis.Backend, cachedfactory = cachedfactory
)