File size: 3,571 Bytes
7a88b43 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
import pickle
from logging import Logger
from pymemcache.client.base import Client
from app.core.config import settings
from app.core.exceptions.base_exception import (
ConnectionException,
CouldNotEditMemcache,
KeyNotFoundException,
)
class Cache:
"""
A generic cache class for interacting with Memcached.
"""
def __init__(self, logger: Logger) -> None:
"""
Initialize the cache connection.
:param logger: Logger instance for logging operations
"""
# Load Memcache config from .env
self.host = settings.CACHE_HOST
self.port = settings.CACHE_HOST
self.default_ttl = settings.CACHE_TTL
self.client = self._initialize_connection()
self.logger = logger
def _initialize_connection(self):
"""
Establish a connection to the Memcached server.
:return: Client instance
:raises ConnectionException: If the connection cannot be established
"""
client = Client((self.host, self.port))
if client:
self.logger.info(f"Connected to Memcached at {self.host}: {self.port}")
return client
else:
raise ConnectionException("Could not connect to Memcached server.")
def add(self, key: str, value: dict):
"""
Add an item to the cache.
:param key: Cache key
:param value: Value to store (serialized using pickle)
:raises CouldNotEditMemcache: If the item could not be added
"""
serialized_value = pickle.dumps(value)
res = self.client.add(key, serialized_value, expire=self.default_ttl)
if not res:
raise CouldNotEditMemcache(f"Could not add key {key} to cache.")
self.logger.info(f"Added {key} to cache.")
def get(self, key: str):
"""
Retrieve an item from the cache.
:param key: Cache key
:return: Deserialized value
:raises KeyNotFoundException: If the key is not found in the cache
"""
byte_string = self.get_raw(key)
return pickle.loads(byte_string)
def get_raw(self, key: str):
"""
Retrieve the raw byte string from the cache.
:param key: Cache key
:return: Raw byte string
:raises KeyNotFoundException: If the key is not found in the cache
"""
byte_string = self.client.get(key)
if not byte_string:
raise KeyNotFoundException(f"Key {key} not found in cache.") # noqa: E713
return byte_string
def delete(self, key: str):
"""
Delete an item from the cache.
:param key: Cache key
:return: Result of the delete operation
:raises CouldNotEditMemcache: If the item could not be deleted
"""
res = self.client.delete(key)
if not res:
raise CouldNotEditMemcache(f"Could not delete key {key} from cache.")
self.logger.info(f"Deleted {key} from cache.")
return res
def update(self, key: str, value: dict):
"""
Update an item in the cache.
:param key: Cache key
:param value: New value to store (serialized using pickle)
:raises CouldNotEditMemcache: If the item could not be updated
"""
serialized_value = pickle.dumps(value)
res = self.client.set(key, serialized_value, expire=self.default_ttl)
if not res:
raise CouldNotEditMemcache(f"Could not update key {key} in cache.")
self.logger.info(f"Updated {key} in cache.")
|