mirror of
https://github.com/GSA/notifications-admin.git
synced 2025-12-17 10:34:07 -05:00
This is easier to read than having to understand the arguments 1…n of
the cache decorator are ‘magic’, and gives us more flexibility about
how the cache keys are formatted, eg being able to add words in the
middle of them.
Also changes the key format for all templates to be
`service-{service_id}-templates` instead of `templates-{service_id}`
because then it’s clearer what the ID represents.
69 lines
2.0 KiB
Python
69 lines
2.0 KiB
Python
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 _get_argument(argument_name, client_method, args, kwargs):
|
||
|
||
with suppress(KeyError):
|
||
return kwargs[argument_name]
|
||
|
||
with suppress(ValueError, IndexError):
|
||
argument_index = list(signature(client_method).parameters).index(argument_name)
|
||
return args[argument_index - 1] # -1 because `args` doesn’t include `self`
|
||
|
||
with suppress(KeyError):
|
||
return signature(client_method).parameters[argument_name].default
|
||
|
||
raise TypeError("{}() takes no argument called '{}'".format(
|
||
client_method.__name__, argument_name
|
||
))
|
||
|
||
|
||
def _make_key(key_format, client_method, args, kwargs):
|
||
return key_format.format(**{
|
||
argument_name: _get_argument(argument_name, client_method, args, kwargs)
|
||
for argument_name in list(signature(client_method).parameters)
|
||
})
|
||
|
||
|
||
def set(key_format):
|
||
|
||
def _set(client_method):
|
||
|
||
@wraps(client_method)
|
||
def new_client_method(client_instance, *args, **kwargs):
|
||
redis_key = _make_key(key_format, client_method, args, kwargs)
|
||
cached = client_instance.redis_client.get(redis_key)
|
||
if cached:
|
||
return json.loads(cached.decode('utf-8'))
|
||
api_response = client_method(client_instance, *args, **kwargs)
|
||
client_instance.redis_client.set(
|
||
redis_key,
|
||
json.dumps(api_response),
|
||
ex=TTL,
|
||
)
|
||
return api_response
|
||
|
||
return new_client_method
|
||
return _set
|
||
|
||
|
||
def delete(key_format):
|
||
|
||
def _delete(client_method):
|
||
|
||
@wraps(client_method)
|
||
def new_client_method(client_instance, *args, **kwargs):
|
||
redis_key = _make_key(key_format, client_method, args, kwargs)
|
||
client_instance.redis_client.delete(redis_key)
|
||
return client_method(client_instance, *args, **kwargs)
|
||
|
||
return new_client_method
|
||
|
||
return _delete
|