Added basic Redis support

This commit is contained in:
Profitroll 2025-02-09 23:37:44 +01:00
parent b3a7e3623a
commit a54ef39e53
Signed by: profitroll
GPG Key ID: FA35CAB49DACD3B2
4 changed files with 96 additions and 31 deletions

View File

@ -2,10 +2,9 @@ import logging
from logging import Logger from logging import Logger
from typing import Dict, Any from typing import Dict, Any
from bson import ObjectId
from pymemcache import Client from pymemcache import Client
from ujson import dumps, loads
from modules.cache_utils import string_to_json, json_to_string
from . import HoloCache from . import HoloCache
logger: Logger = logging.getLogger(__name__) logger: Logger = logging.getLogger(__name__)
@ -17,6 +16,8 @@ class HoloCacheMemcached(HoloCache):
def __init__(self, client: Client): def __init__(self, client: Client):
self.client = client self.client = client
logger.info("Initialized Memcached for caching")
@classmethod @classmethod
def from_config(cls, engine_config: Dict[str, Any]) -> "HoloCacheMemcached": def from_config(cls, engine_config: Dict[str, Any]) -> "HoloCacheMemcached":
if "uri" not in engine_config: if "uri" not in engine_config:
@ -39,7 +40,7 @@ class HoloCacheMemcached(HoloCache):
logger.error("Could not get json cache key '%s' due to: %s", key, exc) logger.error("Could not get json cache key '%s' due to: %s", key, exc)
return None return None
return None if result is None else self._string_to_json(result) return None if result is None else string_to_json(result)
def get_string(self, key: str) -> str | None: def get_string(self, key: str) -> str | None:
try: try:
@ -56,13 +57,13 @@ class HoloCacheMemcached(HoloCache):
logger.error("Could not get string cache key '%s' due to: %s", key, exc) logger.error("Could not get string cache key '%s' due to: %s", key, exc)
return None return None
# TODO Implement binary deserialization
def get_object(self, key: str) -> Any | None: def get_object(self, key: str) -> Any | None:
# TODO Implement binary deserialization
raise NotImplementedError() raise NotImplementedError()
def set_json(self, key: str, value: Any) -> None: def set_json(self, key: str, value: Any) -> None:
try: try:
self.client.set(key, self._json_to_string(value)) self.client.set(key, json_to_string(value))
logger.debug("Set json cache key '%s'", key) logger.debug("Set json cache key '%s'", key)
except Exception as exc: except Exception as exc:
logger.error("Could not set json cache key '%s' due to: %s", key, exc) logger.error("Could not set json cache key '%s' due to: %s", key, exc)
@ -76,8 +77,8 @@ class HoloCacheMemcached(HoloCache):
logger.error("Could not set string cache key '%s' due to: %s", key, exc) logger.error("Could not set string cache key '%s' due to: %s", key, exc)
return None return None
# TODO Implement binary serialization
def set_object(self, key: str, value: Any) -> None: def set_object(self, key: str, value: Any) -> None:
# TODO Implement binary serialization
raise NotImplementedError() raise NotImplementedError()
def delete(self, key: str) -> None: def delete(self, key: str) -> None:
@ -86,21 +87,3 @@ class HoloCacheMemcached(HoloCache):
logger.debug("Deleted cache key '%s'", key) logger.debug("Deleted cache key '%s'", key)
except Exception as exc: except Exception as exc:
logger.error("Could not delete cache key '%s' due to: %s", key, exc) logger.error("Could not delete cache key '%s' due to: %s", key, exc)
@staticmethod
def _json_to_string(json_object: Any) -> str:
if isinstance(json_object, dict) and "_id" in json_object:
json_object["_id"] = str(json_object["_id"])
return dumps(
json_object, ensure_ascii=False, indent=0, escape_forward_slashes=False
)
@staticmethod
def _string_to_json(json_string: str) -> Any:
json_object: Any = loads(json_string)
if isinstance(json_object, dict) and "_id" in json_object:
json_object["_id"] = ObjectId(json_object["_id"])
return json_object

View File

@ -1,34 +1,91 @@
from typing import Dict, Any import logging
from logging import Logger
from typing import Dict, Any, List
from redis import Redis from redis import Redis
from classes.cache import HoloCache from classes.cache import HoloCache
from modules.cache_utils import string_to_json, json_to_string
logger: Logger = logging.getLogger(__name__)
class HoloCacheRedis(HoloCache): class HoloCacheRedis(HoloCache):
client: Redis client: Redis
def __init__(self, client: Redis):
self.client = client
logger.info("Initialized Redis for caching")
@classmethod @classmethod
def from_config(cls, engine_config: Dict[str, Any]) -> Any: def from_config(cls, engine_config: Dict[str, Any]) -> Any:
raise NotImplementedError() if "uri" not in engine_config:
raise KeyError(
"Cache configuration is invalid. Please check if all keys are set (engine: memcached)"
)
uri_split: List[str] = engine_config["uri"].split(":")
return cls(Redis(host=uri_split[0], port=int(uri_split[1])))
def get_json(self, key: str) -> Any | None: def get_json(self, key: str) -> Any | None:
raise NotImplementedError() try:
result: Any | None = self.client.get(key)
logger.debug(
"Got json cache key '%s'%s",
key,
"" if result is not None else " (not found)",
)
except Exception as exc:
logger.error("Could not get json cache key '%s' due to: %s", key, exc)
return None
return None if result is None else string_to_json(result)
def get_string(self, key: str) -> str | None: def get_string(self, key: str) -> str | None:
raise NotImplementedError() try:
result: str | None = self.client.get(key)
logger.debug(
"Got string cache key '%s'%s",
key,
"" if result is not None else " (not found)",
)
return result
except Exception as exc:
logger.error("Could not get string cache key '%s' due to: %s", key, exc)
return None
# TODO Implement binary deserialization
def get_object(self, key: str) -> Any | None: def get_object(self, key: str) -> Any | None:
raise NotImplementedError() raise NotImplementedError()
def set_json(self, key: str, value: Any) -> None: def set_json(self, key: str, value: Any) -> None:
raise NotImplementedError() try:
self.client.set(key, json_to_string(value))
logger.debug("Set json cache key '%s'", key)
except Exception as exc:
logger.error("Could not set json cache key '%s' due to: %s", key, exc)
return None
def set_string(self, key: str, value: str) -> None: def set_string(self, key: str, value: str) -> None:
raise NotImplementedError() try:
self.client.set(key, value)
logger.debug("Set string cache key '%s'", key)
except Exception as exc:
logger.error("Could not set string cache key '%s' due to: %s", key, exc)
return None
# TODO Implement binary serialization
def set_object(self, key: str, value: Any) -> None: def set_object(self, key: str, value: Any) -> None:
raise NotImplementedError() raise NotImplementedError()
def delete(self, key: str) -> None: def delete(self, key: str) -> None:
raise NotImplementedError() try:
self.client.delete(key)
logger.debug("Deleted cache key '%s'", key)
except Exception as exc:
logger.error("Could not delete cache key '%s' due to: %s", key, exc)

View File

@ -15,6 +15,7 @@ class HoloBot(PycordBot):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._set_cache_engine()
def _set_cache_engine(self) -> None: def _set_cache_engine(self) -> None:
if "cache" in self.config and self.config["cache"]["type"] is not None: if "cache" in self.config and self.config["cache"]["type"] is not None:

View File

@ -1,5 +1,9 @@
from copy import deepcopy
from typing import Dict, Any, Literal from typing import Dict, Any, Literal
from bson import ObjectId
from ujson import dumps, loads
from classes.cache.holo_cache_memcached import HoloCacheMemcached from classes.cache.holo_cache_memcached import HoloCacheMemcached
from classes.cache.holo_cache_redis import HoloCacheRedis from classes.cache.holo_cache_redis import HoloCacheRedis
@ -27,3 +31,23 @@ def create_cache_client(
raise KeyError( raise KeyError(
f"Cache implementation for the engine '{engine}' is not present." f"Cache implementation for the engine '{engine}' is not present."
) )
def json_to_string(json_object: Any) -> str:
json_object_copy: Any = deepcopy(json_object)
if isinstance(json_object_copy, dict) and "_id" in json_object_copy:
json_object_copy["_id"] = str(json_object_copy["_id"])
return dumps(
json_object_copy, ensure_ascii=False, indent=0, escape_forward_slashes=False
)
def string_to_json(json_string: str) -> Any:
json_object: Any = loads(json_string)
if "_id" in json_object:
json_object["_id"] = ObjectId(json_object["_id"])
return json_object