Skip to content

Instantly share code, notes, and snippets.

@Cguilliman
Last active March 26, 2021 13:36
Show Gist options
  • Save Cguilliman/95b68fb1e3640dabd94aa46003341b9d to your computer and use it in GitHub Desktop.
Save Cguilliman/95b68fb1e3640dabd94aa46003341b9d to your computer and use it in GitHub Desktop.
Cache all stuff
from typing import *
import time
from django.core.cache import cache
TICKET_AMOUNT = 10
TICK_SIZE = 0.1
def keygen(prefix, *args, **kwargs) -> str:
args_string = '#'.join([str(arg) for arg in sorted(args)])
kwargs_string = '#'.join([
f'{key}~{kwargs.get(key)}'
for key in sorted(kwargs.keys())
if bool(kwargs.get(key))
])
return f"{prefix}@{args_string}@{kwargs_string}"
class Cacher:
def __init__(
self,
structure_getter: Callable[..., Any],
timeout: int = None,
static_key: str = None,
key_gen: Callable[..., str] = None,
tick_amount: int = TICKET_AMOUNT,
tick: float = TICK_SIZE,
):
if not static_key:
raise AttributeError("Must be one of the key `static_key`")
self.static_key = static_key
self.key_gen = key_gen
self.structure_getter = structure_getter
self.timeout = timeout
self.tick_amount = tick_amount
self.tick = tick
def get_key(self, *args, **kwargs):
return (
self.key_gen(self.static_key, *args, **kwargs)
if self.key_gen else self.static_key
)
def get_precache_key(self, key):
return f"{key}||PRECACHE"
def save(self, *args, **kwargs):
key = self.get_key(*args, **kwargs)
precache_key = self.get_precache_key(key)
cache.set(precache_key, True, 10)
data = self.structure_getter(*args, **kwargs)
cache.set(key, data, self.timeout)
return data
def delete_group(self):
cache.delete_pattern(f"{self.static_key}*")
def invalidate(self, *args, **kwargs):
key = self.get_key(*args, **kwargs)
cache.delete(key)
return self.save(*args, **kwargs)
def __get(self, key):
return cache.get(key)
def cache_getter_ticks(self, key):
yield self.__get(key)
is_precached = self.__get(self.get_precache_key(key))
if not is_precached:
return
for _ in range(self.tick_amount):
time.sleep(self.tick)
yield self.__get(key)
def get(self, *args, **kwargs):
for cached_data in self.cache_getter_ticks(self.get_key(*args, **kwargs)):
if cached_data:
return cached_data
# print("------------------ CACHED data")
# print("No cache")
return self.save(*args, **kwargs)
# ============ Example
groups_bundle_cache = Cacher(
structure_getter=get_groups,
timeout=24*60*60,
static_key="GROUPS_BY_SLUG",
key_gen=keygen
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment