WIP: BaseCacheable
This commit is contained in:
0
classes/base/__init__.py
Normal file
0
classes/base/__init__.py
Normal file
107
classes/base/base_cacheable.py
Normal file
107
classes/base/base_cacheable.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
from abc import ABC
|
||||||
|
from logging import Logger
|
||||||
|
from typing import Optional, Any, Dict
|
||||||
|
|
||||||
|
from libbot.cache.classes import Cache
|
||||||
|
|
||||||
|
from classes.abstract import Cacheable
|
||||||
|
from modules.utils import get_logger
|
||||||
|
|
||||||
|
logger: Logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseCacheable(Cacheable, ABC):
|
||||||
|
"""Base implementation of Cacheable used by all cachable classes."""
|
||||||
|
|
||||||
|
async def _set(self, cache: Optional[Cache] = None, **kwargs: Any) -> None:
|
||||||
|
for key, value in kwargs.items():
|
||||||
|
if not hasattr(self, key):
|
||||||
|
raise AttributeError()
|
||||||
|
|
||||||
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
await self.__collection__.update_one({"_id": self._id}, {"$set": kwargs})
|
||||||
|
|
||||||
|
self._update_cache(cache)
|
||||||
|
|
||||||
|
logger.info("Set attributes of %s to %s", self._id, kwargs)
|
||||||
|
|
||||||
|
async def _remove(self, *args: str, cache: Optional[Cache] = None) -> None:
|
||||||
|
attributes: Dict[str, Any] = {}
|
||||||
|
|
||||||
|
for key in args:
|
||||||
|
if not hasattr(self, key):
|
||||||
|
raise AttributeError()
|
||||||
|
|
||||||
|
default_value: Any = self.get_default_value(key)
|
||||||
|
|
||||||
|
setattr(self, key, default_value)
|
||||||
|
|
||||||
|
attributes[key] = default_value
|
||||||
|
|
||||||
|
await self.__collection__.update_one({"_id": self._id}, {"$set": attributes})
|
||||||
|
|
||||||
|
self._update_cache(cache)
|
||||||
|
|
||||||
|
logger.info("Reset attributes %s of %s to default values", args, self._id)
|
||||||
|
|
||||||
|
def _update_cache(self, cache: Optional[Cache] = None) -> None:
|
||||||
|
if cache is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
object_dict: Dict[str, Any] = self.to_dict(json_compatible=True)
|
||||||
|
|
||||||
|
if object_dict is not None:
|
||||||
|
cache.set_json(self._get_cache_key(), object_dict)
|
||||||
|
else:
|
||||||
|
self._delete_cache(cache)
|
||||||
|
|
||||||
|
def _delete_cache(self, cache: Optional[Cache] = None) -> None:
|
||||||
|
if cache is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
cache.delete(self._get_cache_key())
|
||||||
|
|
||||||
|
async def update(
|
||||||
|
self,
|
||||||
|
cache: Optional[Cache] = None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> None:
|
||||||
|
"""Update attribute(s) on the object and save the updated entry into the database.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cache (:obj:`Cache`, optional): Cache engine that will be used to update the cache.
|
||||||
|
**kwargs (Any): Mapping of attributes in format `attribute_name=attribute_value` to update.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AttributeError: Provided attribute does not exist in the class.
|
||||||
|
"""
|
||||||
|
await self._set(cache=cache, **kwargs)
|
||||||
|
|
||||||
|
async def reset(
|
||||||
|
self,
|
||||||
|
*args: str,
|
||||||
|
cache: Optional[Cache] = None,
|
||||||
|
) -> None:
|
||||||
|
"""Remove attribute(s) on the object, replace them with a default value and save the updated entry into the database.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*args (str): List of attributes to remove.
|
||||||
|
cache (:obj:`Cache`, optional): Cache engine that will be used to update the cache.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AttributeError: Provided attribute does not exist in the class.
|
||||||
|
"""
|
||||||
|
await self._remove(*args, cache=cache)
|
||||||
|
|
||||||
|
async def purge(self, cache: Optional[Cache] = None) -> None:
|
||||||
|
"""Completely remove object data from database. Currently only removes the record from a respective collection.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cache (:obj:`Cache`, optional): Cache engine that will be used to update the cache.
|
||||||
|
"""
|
||||||
|
await self.__collection__.delete_one({"_id": self._id})
|
||||||
|
|
||||||
|
self._delete_cache(cache)
|
||||||
|
|
||||||
|
logger.info("Purged %s from the database", self._id)
|
@@ -12,6 +12,7 @@ from pymongo import DESCENDING
|
|||||||
from pymongo.results import InsertOneResult
|
from pymongo.results import InsertOneResult
|
||||||
|
|
||||||
from classes.abstract import Cacheable
|
from classes.abstract import Cacheable
|
||||||
|
from classes.base.base_cacheable import BaseCacheable
|
||||||
from classes.errors import EventNotFoundError
|
from classes.errors import EventNotFoundError
|
||||||
from modules.database import col_events
|
from modules.database import col_events
|
||||||
from modules.utils import get_logger, restore_from_cache
|
from modules.utils import get_logger, restore_from_cache
|
||||||
@@ -20,7 +21,7 @@ logger: Logger = get_logger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PycordEvent(Cacheable):
|
class PycordEvent(BaseCacheable):
|
||||||
"""Object representation of an event in the database.
|
"""Object representation of an event in the database.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
@@ -178,56 +179,19 @@ class PycordEvent(Cacheable):
|
|||||||
return cls(**db_entry)
|
return cls(**db_entry)
|
||||||
|
|
||||||
async def _set(self, cache: Optional[Cache] = None, **kwargs: Any) -> None:
|
async def _set(self, cache: Optional[Cache] = None, **kwargs: Any) -> None:
|
||||||
for key, value in kwargs.items():
|
await super()._set(cache, **kwargs)
|
||||||
if not hasattr(self, key):
|
|
||||||
raise AttributeError(f"Attribute '{key}' does not exist in PycordEvent")
|
|
||||||
|
|
||||||
setattr(self, key, value)
|
|
||||||
|
|
||||||
await self.__collection__.update_one({"_id": self._id}, {"$set": kwargs}, upsert=True)
|
|
||||||
|
|
||||||
self._update_cache(cache)
|
|
||||||
|
|
||||||
logger.info("Set attributes of event %s to %s", self._id, kwargs)
|
|
||||||
|
|
||||||
async def _remove(self, *args: str, cache: Optional[Cache] = None) -> None:
|
async def _remove(self, *args: str, cache: Optional[Cache] = None) -> None:
|
||||||
attributes: Dict[str, Any] = {}
|
await super()._remove(*args, cache=cache)
|
||||||
|
|
||||||
for key in args:
|
|
||||||
if not hasattr(self, key):
|
|
||||||
raise AttributeError(f"Attribute '{key}' does not exist in PycordEvent")
|
|
||||||
|
|
||||||
default_value: Any = self.get_default_value(key)
|
|
||||||
|
|
||||||
setattr(self, key, default_value)
|
|
||||||
|
|
||||||
attributes[key] = default_value
|
|
||||||
|
|
||||||
await self.__collection__.update_one({"_id": self._id}, {"$set": attributes}, upsert=True)
|
|
||||||
|
|
||||||
self._update_cache(cache)
|
|
||||||
|
|
||||||
logger.info("Reset attributes %s of event %s to default values", args, self._id)
|
|
||||||
|
|
||||||
def _get_cache_key(self) -> str:
|
def _get_cache_key(self) -> str:
|
||||||
return f"{self.__short_name__}_{self._id}"
|
return f"{self.__short_name__}_{self._id}"
|
||||||
|
|
||||||
def _update_cache(self, cache: Optional[Cache] = None) -> None:
|
def _update_cache(self, cache: Optional[Cache] = None) -> None:
|
||||||
if cache is None:
|
super()._update_cache(cache)
|
||||||
return
|
|
||||||
|
|
||||||
object_dict: Dict[str, Any] = self.to_dict(json_compatible=True)
|
|
||||||
|
|
||||||
if object_dict is not None:
|
|
||||||
cache.set_json(self._get_cache_key(), object_dict)
|
|
||||||
else:
|
|
||||||
self._delete_cache(cache)
|
|
||||||
|
|
||||||
def _delete_cache(self, cache: Optional[Cache] = None) -> None:
|
def _delete_cache(self, cache: Optional[Cache] = None) -> None:
|
||||||
if cache is None:
|
super()._delete_cache(cache)
|
||||||
return
|
|
||||||
|
|
||||||
cache.delete(self._get_cache_key())
|
|
||||||
|
|
||||||
async def _update_event_stage_order(
|
async def _update_event_stage_order(
|
||||||
self,
|
self,
|
||||||
@@ -348,45 +312,21 @@ class PycordEvent(Cacheable):
|
|||||||
return PycordEvent.get_defaults()[key]
|
return PycordEvent.get_defaults()[key]
|
||||||
|
|
||||||
async def update(
|
async def update(
|
||||||
self,
|
self,
|
||||||
cache: Optional[Cache] = None,
|
cache: Optional[Cache] = None,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Update attribute(s) on the object and save the updated entry into the database.
|
await super().update(cache=cache, **kwargs)
|
||||||
|
|
||||||
Args:
|
|
||||||
cache (:obj:`Cache`, optional): Cache engine that will be used to update the cache.
|
|
||||||
**kwargs (Any): Mapping of attributes in format `attribute_name=attribute_value` to update.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
AttributeError: Provided attribute does not exist in the class.
|
|
||||||
"""
|
|
||||||
await self._set(cache=cache, **kwargs)
|
|
||||||
|
|
||||||
async def reset(
|
async def reset(
|
||||||
self,
|
self,
|
||||||
*args: str,
|
*args: str,
|
||||||
cache: Optional[Cache] = None,
|
cache: Optional[Cache] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Remove attribute(s) on the object, replace them with a default value and save the updated entry into the database.
|
await super().reset(*args, cache=cache)
|
||||||
|
|
||||||
Args:
|
|
||||||
*args (str): List of attributes to remove.
|
|
||||||
cache (:obj:`Cache`, optional): Cache engine that will be used to update the cache.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
AttributeError: Provided attribute does not exist in the class.
|
|
||||||
"""
|
|
||||||
await self._remove(*args, cache=cache)
|
|
||||||
|
|
||||||
async def purge(self, cache: Optional[Cache] = None) -> None:
|
async def purge(self, cache: Optional[Cache] = None) -> None:
|
||||||
"""Completely remove event data from database. Currently only removes the event record from events collection.
|
await super().purge(cache)
|
||||||
|
|
||||||
Args:
|
|
||||||
cache (:obj:`Cache`, optional): Cache engine that will be used to update the cache.
|
|
||||||
"""
|
|
||||||
await self.__collection__.delete_one({"_id": self._id})
|
|
||||||
self._delete_cache(cache)
|
|
||||||
|
|
||||||
async def cancel(self, cache: Optional[Cache] = None) -> None:
|
async def cancel(self, cache: Optional[Cache] = None) -> None:
|
||||||
"""Cancel the event.
|
"""Cancel the event.
|
||||||
|
@@ -122,7 +122,7 @@ class PycordEventStage(Cacheable):
|
|||||||
|
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
await self.__collection__.update_one({"_id": self._id}, {"$set": kwargs}, upsert=True)
|
await self.__collection__.update_one({"_id": self._id}, {"$set": kwargs})
|
||||||
|
|
||||||
self._update_cache(cache)
|
self._update_cache(cache)
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ class PycordEventStage(Cacheable):
|
|||||||
|
|
||||||
attributes[key] = default_value
|
attributes[key] = default_value
|
||||||
|
|
||||||
await self.__collection__.update_one({"_id": self._id}, {"$set": attributes}, upsert=True)
|
await self.__collection__.update_one({"_id": self._id}, {"$set": attributes})
|
||||||
|
|
||||||
self._update_cache(cache)
|
self._update_cache(cache)
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ from bson import ObjectId
|
|||||||
from libbot.cache.classes import Cache
|
from libbot.cache.classes import Cache
|
||||||
from pymongo.results import InsertOneResult
|
from pymongo.results import InsertOneResult
|
||||||
|
|
||||||
from classes.abstract import Cacheable
|
from classes.base.base_cacheable import BaseCacheable
|
||||||
from classes.errors import GuildNotFoundError
|
from classes.errors import GuildNotFoundError
|
||||||
from modules.database import col_guilds
|
from modules.database import col_guilds
|
||||||
from modules.utils import get_logger, restore_from_cache
|
from modules.utils import get_logger, restore_from_cache
|
||||||
@@ -15,7 +15,7 @@ logger: Logger = get_logger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PycordGuild(Cacheable):
|
class PycordGuild(BaseCacheable):
|
||||||
"""Dataclass of DB entry of a guild"""
|
"""Dataclass of DB entry of a guild"""
|
||||||
|
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
@@ -78,56 +78,60 @@ class PycordGuild(Cacheable):
|
|||||||
return cls(**db_entry)
|
return cls(**db_entry)
|
||||||
|
|
||||||
async def _set(self, cache: Optional[Cache] = None, **kwargs: Any) -> None:
|
async def _set(self, cache: Optional[Cache] = None, **kwargs: Any) -> None:
|
||||||
for key, value in kwargs.items():
|
await super()._set(cache, **kwargs)
|
||||||
if not hasattr(self, key):
|
# for key, value in kwargs.items():
|
||||||
raise AttributeError()
|
# if not hasattr(self, key):
|
||||||
|
# raise AttributeError()
|
||||||
setattr(self, key, value)
|
#
|
||||||
|
# setattr(self, key, value)
|
||||||
await self.__collection__.update_one({"_id": self._id}, {"$set": kwargs}, upsert=True)
|
#
|
||||||
|
# await self.__collection__.update_one({"_id": self._id}, {"$set": kwargs})
|
||||||
self._update_cache(cache)
|
#
|
||||||
|
# self._update_cache(cache)
|
||||||
logger.info("Set attributes of guild %s to %s", self.id, kwargs)
|
#
|
||||||
|
# logger.info("Set attributes of guild %s to %s", self.id, kwargs)
|
||||||
|
|
||||||
async def _remove(self, *args: str, cache: Optional[Cache] = None) -> None:
|
async def _remove(self, *args: str, cache: Optional[Cache] = None) -> None:
|
||||||
attributes: Dict[str, Any] = {}
|
await super()._remove(*args, cache=cache)
|
||||||
|
# attributes: Dict[str, Any] = {}
|
||||||
for key in args:
|
#
|
||||||
if not hasattr(self, key):
|
# for key in args:
|
||||||
raise AttributeError()
|
# if not hasattr(self, key):
|
||||||
|
# raise AttributeError()
|
||||||
default_value: Any = self.get_default_value(key)
|
#
|
||||||
|
# default_value: Any = self.get_default_value(key)
|
||||||
setattr(self, key, default_value)
|
#
|
||||||
|
# setattr(self, key, default_value)
|
||||||
attributes[key] = default_value
|
#
|
||||||
|
# attributes[key] = default_value
|
||||||
await self.__collection__.update_one({"_id": self._id}, {"$set": attributes}, upsert=True)
|
#
|
||||||
|
# await self.__collection__.update_one({"_id": self._id}, {"$set": attributes})
|
||||||
self._update_cache(cache)
|
#
|
||||||
|
# self._update_cache(cache)
|
||||||
logger.info("Reset attributes %s of guild %s to default values", args, self.id)
|
#
|
||||||
|
# logger.info("Reset attributes %s of guild %s to default values", args, self.id)
|
||||||
|
|
||||||
def _get_cache_key(self) -> str:
|
def _get_cache_key(self) -> str:
|
||||||
return f"{self.__short_name__}_{self.id}"
|
return f"{self.__short_name__}_{self.id}"
|
||||||
|
|
||||||
def _update_cache(self, cache: Optional[Cache] = None) -> None:
|
def _update_cache(self, cache: Optional[Cache] = None) -> None:
|
||||||
if cache is None:
|
super()._update_cache(cache)
|
||||||
return
|
# if cache is None:
|
||||||
|
# return
|
||||||
object_dict: Dict[str, Any] = self.to_dict(json_compatible=True)
|
#
|
||||||
|
# object_dict: Dict[str, Any] = self.to_dict(json_compatible=True)
|
||||||
if object_dict is not None:
|
#
|
||||||
cache.set_json(self._get_cache_key(), object_dict)
|
# if object_dict is not None:
|
||||||
else:
|
# cache.set_json(self._get_cache_key(), object_dict)
|
||||||
self._delete_cache(cache)
|
# else:
|
||||||
|
# self._delete_cache(cache)
|
||||||
|
|
||||||
def _delete_cache(self, cache: Optional[Cache] = None) -> None:
|
def _delete_cache(self, cache: Optional[Cache] = None) -> None:
|
||||||
if cache is None:
|
super()._delete_cache(cache)
|
||||||
return
|
# if cache is None:
|
||||||
|
# return
|
||||||
cache.delete(self._get_cache_key())
|
#
|
||||||
|
# cache.delete(self._get_cache_key())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _entry_to_cache(db_entry: Dict[str, Any]) -> Dict[str, Any]:
|
def _entry_to_cache(db_entry: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
@@ -203,32 +207,14 @@ class PycordGuild(Cacheable):
|
|||||||
cache: Optional[Cache] = None,
|
cache: Optional[Cache] = None,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Update attribute(s) on the object and save the updated entry into the database.
|
await super().update(cache=cache, **kwargs)
|
||||||
|
|
||||||
Args:
|
|
||||||
cache (:obj:`Cache`, optional): Cache engine that will be used to update the cache.
|
|
||||||
**kwargs (Any): Mapping of attributes in format `attribute_name=attribute_value` to update.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
AttributeError: Provided attribute does not exist in the class.
|
|
||||||
"""
|
|
||||||
await self._set(cache=cache, **kwargs)
|
|
||||||
|
|
||||||
async def reset(
|
async def reset(
|
||||||
self,
|
self,
|
||||||
*args: str,
|
*args: str,
|
||||||
cache: Optional[Cache] = None,
|
cache: Optional[Cache] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Remove attribute(s) on the object, replace them with a default value and save the updated entry into the database.
|
await super().reset(*args, cache=cache)
|
||||||
|
|
||||||
Args:
|
|
||||||
*args (str): List of attributes to remove.
|
|
||||||
cache (:obj:`Cache`, optional): Cache engine that will be used to update the cache.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
AttributeError: Provided attribute does not exist in the class.
|
|
||||||
"""
|
|
||||||
await self._remove(*args, cache=cache)
|
|
||||||
|
|
||||||
async def purge(self, cache: Optional[Cache] = None) -> None:
|
async def purge(self, cache: Optional[Cache] = None) -> None:
|
||||||
"""Completely remove guild data from database. Currently only removes the guild record from guilds collection.
|
"""Completely remove guild data from database. Currently only removes the guild record from guilds collection.
|
||||||
@@ -236,11 +222,7 @@ class PycordGuild(Cacheable):
|
|||||||
Args:
|
Args:
|
||||||
cache (:obj:`Cache`, optional): Cache engine to write the update into
|
cache (:obj:`Cache`, optional): Cache engine to write the update into
|
||||||
"""
|
"""
|
||||||
await self.__collection__.delete_one({"_id": self._id})
|
await super().purge(cache)
|
||||||
|
|
||||||
self._delete_cache(cache)
|
|
||||||
|
|
||||||
logger.info("Purged guild %s (%s) from the database", self.id, self._id)
|
|
||||||
|
|
||||||
def is_configured(self) -> bool:
|
def is_configured(self) -> bool:
|
||||||
"""Return whether all attributes required for bot's use on the server are set.
|
"""Return whether all attributes required for bot's use on the server are set.
|
||||||
|
@@ -157,7 +157,7 @@ class PycordUser(Cacheable):
|
|||||||
|
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
await self.__collection__.update_one({"_id": self._id}, {"$set": kwargs}, upsert=True)
|
await self.__collection__.update_one({"_id": self._id}, {"$set": kwargs})
|
||||||
|
|
||||||
self._update_cache(cache)
|
self._update_cache(cache)
|
||||||
|
|
||||||
@@ -182,14 +182,14 @@ class PycordUser(Cacheable):
|
|||||||
|
|
||||||
attributes[key] = default_value
|
attributes[key] = default_value
|
||||||
|
|
||||||
await self.__collection__.update_one({"_id": self._id}, {"$set": attributes}, upsert=True)
|
await self.__collection__.update_one({"_id": self._id}, {"$set": attributes})
|
||||||
|
|
||||||
self._update_cache(cache)
|
self._update_cache(cache)
|
||||||
|
|
||||||
logger.info("Reset attributes %s of user %s to default values", args, self.id)
|
logger.info("Reset attributes %s of user %s to default values", args, self.id)
|
||||||
|
|
||||||
def _get_cache_key(self) -> str:
|
def _get_cache_key(self) -> str:
|
||||||
return f"{self.__short_name__}_{self.id}"
|
return f"{self.__short_name__}_{self.id}_{self.guild_id}"
|
||||||
|
|
||||||
def _update_cache(self, cache: Optional[Cache] = None) -> None:
|
def _update_cache(self, cache: Optional[Cache] = None) -> None:
|
||||||
if cache is None:
|
if cache is None:
|
||||||
|
Reference in New Issue
Block a user