diff --git a/naff/client/client.py b/naff/client/client.py index bc7cbec6b..7d923e37c 100644 --- a/naff/client/client.py +++ b/naff/client/client.py @@ -49,6 +49,7 @@ NotFound, ) from naff.client.smart_cache import GlobalCache +from naff.client.utils import NullCache from naff.client.utils.input_utils import get_first_word, get_args from naff.client.utils.misc_utils import get_event_name, wrap_partial from naff.client.utils.serializer import to_image_data @@ -527,6 +528,16 @@ def _sanity_check(self) -> None: if len(self.processors) == 0: self.logger.warning("No Processors are loaded! This means no events will be processed!") + caches = [ + c[0] + for c in inspect.getmembers(self.cache, predicate=lambda x: isinstance(x, dict)) + if not c[0].startswith("__") + ] + for cache in caches: + _cache_obj = getattr(self.cache, cache) + if isinstance(_cache_obj, NullCache): + self.logger.warning(f"{cache} has been disabled") + async def generate_prefixes(self, bot: "Client", message: Message) -> str | Iterable[str]: """ A method to get the bot's default_prefix, can be overridden to add dynamic prefixes. diff --git a/naff/client/smart_cache.py b/naff/client/smart_cache.py index 03b438f37..571ebee88 100644 --- a/naff/client/smart_cache.py +++ b/naff/client/smart_cache.py @@ -7,7 +7,7 @@ from naff.client.const import Absent, MISSING, get_logger from naff.client.errors import NotFound, Forbidden -from naff.client.utils.cache import TTLCache +from naff.client.utils.cache import TTLCache, NullCache from naff.models import VoiceState from naff.models.discord.channel import BaseChannel, GuildChannel, ThreadChannel from naff.models.discord.emoji import CustomEmoji @@ -29,7 +29,7 @@ def create_cache( ttl: Optional[int] = 60, hard_limit: Optional[int] = 250, soft_limit: Absent[Optional[int]] = MISSING -) -> Union[dict, TTLCache]: +) -> Union[dict, TTLCache, NullCache]: """ Create a cache object based on the parameters passed. @@ -46,6 +46,8 @@ def create_cache( """ if ttl is None and hard_limit is None: return {} + if ttl == 0 and hard_limit == 0 and soft_limit == 0: + return NullCache() else: if not soft_limit: soft_limit = int(hard_limit / 4) if hard_limit else 50 diff --git a/naff/client/utils/cache.py b/naff/client/utils/cache.py index e691c5c40..e89c99ccb 100644 --- a/naff/client/utils/cache.py +++ b/naff/client/utils/cache.py @@ -5,12 +5,23 @@ import attrs -__all__ = ("TTLItem", "TTLCache") +__all__ = ("TTLItem", "TTLCache", "NullCache") KT = TypeVar("KT") VT = TypeVar("VT") +class NullCache(dict): + """ + A special cache that will always return None + + Effectively just a lazy way to disable caching. + """ + + def __setitem__(self, key, value) -> None: + pass + + @attrs.define(eq=False, order=False, hash=False, kw_only=False) class TTLItem(Generic[VT]): value: VT = attrs.field( diff --git a/naff/ext/debug_extension/utils.py b/naff/ext/debug_extension/utils.py index 538407dcb..5ccc6a484 100644 --- a/naff/ext/debug_extension/utils.py +++ b/naff/ext/debug_extension/utils.py @@ -1,8 +1,9 @@ import datetime import inspect +import weakref from typing import TYPE_CHECKING, Any, Optional, Union -from naff.client.utils.cache import TTLCache +from naff.client.utils.cache import TTLCache, NullCache from naff.models import Embed, MaterialColors if TYPE_CHECKING: @@ -28,19 +29,26 @@ def debug_embed(title: str, **kwargs) -> Embed: def get_cache_state(bot: "Client") -> str: """Create a nicely formatted table of internal cache state.""" - caches = [ - c[0] + caches = { + c[0]: getattr(bot.cache, c[0]) for c in inspect.getmembers(bot.cache, predicate=lambda x: isinstance(x, dict)) if not c[0].startswith("__") - ] + } + caches["endpoints"] = bot.http._endpoints + caches["rate_limits"] = bot.http.ratelimit_locks table = [] - for cache in caches: - val = getattr(bot.cache, cache) + for cache, val in caches.items(): if isinstance(val, TTLCache): amount = [len(val), f"{val.hard_limit}({val.soft_limit})"] expire = f"{val.ttl}s" + elif isinstance(val, NullCache): + amount = ("DISABLED",) + expire = "N/A" + elif isinstance(val, (weakref.WeakValueDictionary, weakref.WeakKeyDictionary)): + amount = [len(val), "∞"] + expire = "w_ref" else: amount = [len(val), "∞"] expire = "none" @@ -48,10 +56,6 @@ def get_cache_state(bot: "Client") -> str: row = [cache.removesuffix("_cache"), amount, expire] table.append(row) - # http caches - table.append(["endpoints", [len(bot.http._endpoints), "∞"], "none"]) - table.append(["ratelimits", [len(bot.http.ratelimit_locks), "∞"], "w_ref"]) - adjust_subcolumn(table, 1, aligns=[">", "<"]) labels = ["Cache", "Amount", "Expire"]