mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-28 11:49:13 -04:00
Rewrite cache decorator to reference args by name
`@cache.delete('user', 'user_id')` is easier to read and understand than
`@cache.delete('user', key_from_args=[1])`. This will become even more
apparent if we have to start doing stuff like `key_from_args=[1, 5]`,
which is a lot more opaque than just saying
`'service_id', 'template_id'`.
It does make the implementation a bit more complex, but I’m not too
worried about that because:
- the tests are solid
- it’s nicely encapsulated
This commit is contained in:
@@ -1,27 +1,51 @@
|
||||
import json
|
||||
from contextlib import suppress
|
||||
from datetime import timedelta
|
||||
from functools import wraps
|
||||
from inspect import signature
|
||||
|
||||
TTL = int(timedelta(hours=24).total_seconds())
|
||||
|
||||
|
||||
def _make_key(prefix, args, key_from_args):
|
||||
def _get_argument(argument_name, args, kwargs, client_method):
|
||||
|
||||
if key_from_args is None:
|
||||
key_from_args = [0]
|
||||
with suppress(KeyError):
|
||||
return kwargs[argument_name]
|
||||
|
||||
with suppress(ValueError):
|
||||
return args[list(signature(client_method).parameters).index(argument_name) - 1]
|
||||
|
||||
raise TypeError("{}() takes no argument called '{}'".format(
|
||||
client_method.__name__, argument_name
|
||||
))
|
||||
|
||||
|
||||
def list_of_strings(list_of_stuff):
|
||||
return list(map(str, filter(None, list_of_stuff)))
|
||||
|
||||
|
||||
def _make_key(prefix, key_from_args, local_variables):
|
||||
return '-'.join(
|
||||
[prefix] + [args[index] for index in key_from_args]
|
||||
[
|
||||
local_variables['prefix']
|
||||
] + list_of_strings(
|
||||
_get_argument(
|
||||
argument_name,
|
||||
local_variables['args'],
|
||||
local_variables['kwargs'],
|
||||
local_variables['client_method']
|
||||
) for argument_name in key_from_args
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def set(prefix, key_from_args=None):
|
||||
def set(prefix, *key_from_args):
|
||||
|
||||
def _set(client_method):
|
||||
|
||||
@wraps(client_method)
|
||||
def new_client_method(client_instance, *args, **kwargs):
|
||||
redis_key = _make_key(prefix, args, key_from_args)
|
||||
redis_key = _make_key(prefix, key_from_args, locals())
|
||||
cached = client_instance.redis_client.get(redis_key)
|
||||
if cached:
|
||||
return json.loads(cached.decode('utf-8'))
|
||||
@@ -37,13 +61,13 @@ def set(prefix, key_from_args=None):
|
||||
return _set
|
||||
|
||||
|
||||
def delete(prefix, key_from_args=None):
|
||||
def delete(prefix, *key_from_args):
|
||||
|
||||
def _delete(client_method):
|
||||
|
||||
@wraps(client_method)
|
||||
def new_client_method(client_instance, *args, **kwargs):
|
||||
redis_key = _make_key(prefix, args, key_from_args)
|
||||
redis_key = _make_key(prefix, key_from_args, locals())
|
||||
client_instance.redis_client.delete(redis_key)
|
||||
return client_method(client_instance, *args, **kwargs)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user