r_cache

privex.helpers.decorators.r_cache(cache_key: Union[str, callable], cache_time=300, format_args: list = None, format_opt: privex.helpers.decorators.FormatOpt = <FormatOpt.POS_AUTO: 'force_pos'>, **opts) → Any[source]

This is a decorator which caches the result of the wrapped function with the global cache adapter from privex.helpers.cache using the key cache_key and with an expiry of cache_time seconds.

Future calls to the wrapped function would then load the data from cache until the cache expires, upon which it will re-run the original code and re-cache it.

To bypass the cache, pass kwarg r_cache=False to the wrapped function. To override the cache key on demand, pass r_cache_key='mykey' to the wrapped function.

Example usage:

>>> from privex.helpers import r_cache
>>>
>>> @r_cache('mydata', cache_time=600)
... def my_func(*args, **kwargs):
...     time.sleep(60)
...     return "done"

This will run the function and take 60 seconds to return while it sleeps

>>> my_func()
done

This will run instantly because “done” is now cached for 600 seconds

>>> my_func()
done

This will take another 60 seconds to run because r_cache is set to False (disables the cache)

>>> my_func(r_cache=False)
done

Using a dynamic cache_key:

Simplest and most reliable - pass ``r_cache_key`` as an additional kwarg

If you don’t mind passing an additional kwarg to your function, then the most reliable method is to override the cache key by passing r_cache_key to your wrapped function.

Don’t worry, we remove both r_cache and r_cache_key from the kwargs that actually hit your function.

>>> my_func(r_cache_key='somekey')    # Use the cache key 'somekey' when caching data for this function

Option 2. Pass a callable which takes the same arguments as the wrapped function

In the example below, who takes two arguments: name and title - we then pass the function make_key which takes the same arguments - r_cache will detect that the cache key is a function and call it with the same (*args, **kwargs) passed to the wrapped function.

>>> from privex.helpers import r_cache
>>>
>>> def make_key(name, title):
...     return f"mycache:{name}"
...
>>> @r_cache(make_key)
... def who(name, title):
...     return "Their name is {title} {name}"
...

We can also obtain the same effect with a lambda callable defined directly inside of the cache_key.

>>> @r_cache(lambda name,title: f"mycache:{name}")
... def who(name, title):
...     return "Their name is {title} {name}"

Option 3. Can be finnicky - using ``format_args`` to integrate with existing code

If you can’t change how your existing function/method is called, then you can use the format_args feature.

NOTE: Unless you’re forcing the usage of kwargs with a function/method, it’s strongly recommended that you keep force_pos enabled, and specify both the positional argument ID, and the kwarg name.

Basic Example:

>>> from privex.helpers import r_cache
>>> import time
>>>
>>> @r_cache('some_cache:{}:{}', cache_time=600, format_args=[0, 1, 'x', 'y'])
... def some_func(x=1, y=2):
...     time.sleep(5)
...     return 'x + y = {}'.format(x + y)
>>>

Using positional arguments, we can see from the debug log that it’s formatting the {}:{} in the key with x:y

>>> some_func(1, 2)
2019-08-21 06:58:29,823 lg  DEBUG    Trying to load "some_cache:1:2" from cache
2019-08-21 06:58:29,826 lg  DEBUG    Not found in cache, or "r_cache" set to false. Calling wrapped function.
'x + y = 3'
>>> some_func(2, 3)
2019-08-21 06:58:34,831 lg  DEBUG    Trying to load "some_cache:2:3" from cache
2019-08-21 06:58:34,832 lg  DEBUG    Not found in cache, or "r_cache" set to false. Calling wrapped function.
'x + y = 5'

When we passed (1, 2) and (2, 3) it had to re-run the function for each. But once we re-call it for the previously ran (1, 2) - it’s able to retrieve the cached result just for those args.

>>> some_func(1, 2)
2019-08-21 06:58:41,752 lg  DEBUG    Trying to load "some_cache:1:2" from cache
'x + y = 3'

Be warned that the default format option POS_AUTO will make kwargs’ values be specified in the same order as they were listed in format_args

>>> some_func(y=1, x=2)   # ``format_args`` has the kwargs in the order ``['x', 'y']`` thus ``.format(x,y)``
2019-08-21 06:58:58,611 lg  DEBUG    Trying to load "some_cache:2:1" from cache
2019-08-21 06:58:58,611 lg  DEBUG    Not found in cache, or "r_cache" set to false. Calling wrapped function.
'x + y = 3'
Parameters
  • format_opt (FormatOpt) – (default: FormatOpt.POS_AUTO) “Format option” - how should args/kwargs be used when filling placeholders in the cache_key (see comments on FormatOption)

  • format_args (list) – A list of positional arguments numbers (e.g. [0, 1, 2]) and/or kwargs ['x', 'y', 'z'] that should be used to format the cache_key

  • cache_key (str) – The cache key to store the cached data into, e.g. mydata

  • cache_time (int) – The amount of time in seconds to cache the result for (default: 300 seconds)

  • whitelist (bool) – (default: True) If True, only use specified arg positions / kwarg keys when formatting cache_key placeholders. Otherwise, trust whatever args/kwargs were passed to the func.

Return Any res

The return result, either from the wrapped function, or from the cache.