114 lines
3.1 KiB
Python
Raw Normal View History

2025-01-24 23:35:44 +01:00
import functools
2025-01-25 22:24:44 +01:00
import json
2025-01-25 22:28:33 +01:00
from snek.system import security
2025-01-24 16:09:10 +01:00
cache = functools.cache
2025-01-25 22:28:33 +01:00
CACHE_MAX_ITEMS_DEFAULT = 5000
2025-01-25 22:24:44 +01:00
class Cache:
2025-01-25 22:28:33 +01:00
def __init__(self, app, max_items=CACHE_MAX_ITEMS_DEFAULT):
2025-01-25 22:24:44 +01:00
self.app = app
self.cache = {}
self.max_items = max_items
self.lru = []
2025-01-25 22:28:33 +01:00
self.version = ((42 + 420 + 1984 + 1990 + 10 + 6 + 71 + 3004 + 7245) ^ 1337) + 4
2025-01-25 22:24:44 +01:00
async def get(self, args):
try:
self.lru.pop(self.lru.index(args))
except:
2025-01-25 22:28:33 +01:00
print("Cache miss!", args, flush=True)
2025-01-25 22:24:44 +01:00
return None
self.lru.insert(0, args)
2025-01-25 22:28:33 +01:00
while len(self.lru) > self.max_items:
2025-01-25 22:24:44 +01:00
self.cache.pop(self.lru[-1])
self.lru.pop()
2025-01-25 22:28:33 +01:00
print("Cache hit!", args, flush=True)
2025-01-25 22:24:44 +01:00
return self.cache[args]
def json_default(self, value):
2025-01-25 22:28:33 +01:00
# if hasattr(value, "to_json"):
2025-01-25 22:24:44 +01:00
# return value.to_json()
try:
return json.dumps(value.__dict__, default=str)
except:
return str(value)
async def create_cache_key(self, args, kwargs):
2025-01-25 22:28:33 +01:00
return await security.hash(
json.dumps(
{"args": args, "kwargs": kwargs},
sort_keys=True,
default=self.json_default,
)
)
2025-01-25 22:24:44 +01:00
async def set(self, args, result):
2025-01-25 22:28:33 +01:00
is_new = args not in self.cache
2025-01-25 22:24:44 +01:00
self.cache[args] = result
try:
self.lru.pop(self.lru.index(args))
2025-01-25 22:28:33 +01:00
except (ValueError, IndexError):
pass
self.lru.insert(0, args)
2025-01-25 22:24:44 +01:00
2025-01-25 22:28:33 +01:00
while len(self.lru) > self.max_items:
2025-01-25 22:24:44 +01:00
self.cache.pop(self.lru[-1])
self.lru.pop()
if is_new:
self.version += 1
2025-01-27 03:48:53 +01:00
print("Cache store! New version:", self.version, flush=True)
2025-01-25 22:24:44 +01:00
async def delete(self, args):
2025-01-25 22:28:33 +01:00
if args in self.cache:
2025-01-25 22:24:44 +01:00
try:
self.lru.pop(self.lru.index(args))
except IndexError:
2025-01-25 22:28:33 +01:00
pass
2025-01-25 22:24:44 +01:00
del self.cache[args]
2025-01-25 22:28:33 +01:00
def async_cache(self, func):
2025-01-25 22:24:44 +01:00
@functools.wraps(func)
2025-01-25 22:28:33 +01:00
async def wrapper(*args, **kwargs):
cache_key = await self.create_cache_key(args, kwargs)
2025-01-25 22:24:44 +01:00
cached = await self.get(cache_key)
if cached:
return cached
2025-01-25 22:28:33 +01:00
result = await func(*args, **kwargs)
await self.set(cache_key, result)
2025-01-25 22:24:44 +01:00
return result
2025-01-25 22:28:33 +01:00
return wrapper
2025-01-25 22:24:44 +01:00
2025-01-25 22:28:33 +01:00
def async_delete_cache(self, func):
2025-01-25 22:24:44 +01:00
@functools.wraps(func)
2025-01-25 22:28:33 +01:00
async def wrapper(*args, **kwargs):
cache_key = await self.create_cache_key(args, kwargs)
2025-01-25 22:24:44 +01:00
if cache_key in self.cache:
try:
self.lru.pop(self.lru.index(cache_key))
except IndexError:
2025-01-25 22:28:33 +01:00
pass
2025-01-25 22:24:44 +01:00
del self.cache[cache_key]
return await func(*args, **kwargs)
2025-01-25 22:28:33 +01:00
2025-01-25 22:24:44 +01:00
return wrapper
2025-01-24 23:35:44 +01:00
2025-01-24 16:09:10 +01:00
def async_cache(func):
cache = {}
@functools.wraps(func)
async def wrapper(*args):
if args in cache:
return cache[args]
result = await func(*args)
cache[args] = result
return result
2025-01-24 23:35:44 +01:00
return wrapper