diff options
Diffstat (limited to '')
| -rw-r--r-- | bot/exts/info/doc.py | 7 | ||||
| -rw-r--r-- | bot/exts/utils/utils.py | 5 | ||||
| -rw-r--r-- | bot/utils/cache.py | 49 | 
3 files changed, 37 insertions, 24 deletions
diff --git a/bot/exts/info/doc.py b/bot/exts/info/doc.py index 06dd4df63..ba443d817 100644 --- a/bot/exts/info/doc.py +++ b/bot/exts/info/doc.py @@ -22,7 +22,7 @@ from bot.bot import Bot  from bot.constants import MODERATION_ROLES, RedirectOutput  from bot.converters import ValidPythonIdentifier, ValidURL  from bot.pagination import LinePaginator -from bot.utils.cache import async_cache +from bot.utils.cache import AsyncCache  from bot.utils.messages import wait_for_deletion @@ -66,6 +66,9 @@ WHITESPACE_AFTER_NEWLINES_RE = re.compile(r"(?<=\n\n)(\s+)")  FAILED_REQUEST_RETRY_AMOUNT = 3  NOT_FOUND_DELETE_DELAY = RedirectOutput.delete_delay +# Async cache instance for docs cog +async_cache = AsyncCache() +  class DocMarkdownConverter(MarkdownConverter):      """Subclass markdownify's MarkdownCoverter to provide custom conversion methods.""" @@ -187,7 +190,7 @@ class Doc(commands.Cog):          self.base_urls.clear()          self.inventories.clear()          self.renamed_symbols.clear() -        async_cache.cache["get_symbol_embed"] = OrderedDict() +        async_cache.clear()          # Run all coroutines concurrently - since each of them performs a HTTP          # request, this speeds up fetching the inventory data heavily. diff --git a/bot/exts/utils/utils.py b/bot/exts/utils/utils.py index 2a74af172..64d42c93e 100644 --- a/bot/exts/utils/utils.py +++ b/bot/exts/utils/utils.py @@ -15,7 +15,7 @@ from bot.constants import Channels, MODERATION_ROLES, STAFF_ROLES  from bot.decorators import in_whitelist  from bot.pagination import LinePaginator  from bot.utils import messages -from bot.utils.cache import async_cache +from bot.utils.cache import AsyncCache  log = logging.getLogger(__name__) @@ -43,6 +43,9 @@ Namespaces are one honking great idea -- let's do more of those!  ICON_URL = "https://www.python.org/static/opengraph-icon-200x200.png" +# Async cache instance for PEPs +async_cache = AsyncCache() +  class Utils(Cog):      """A selection of utilities which don't have a clear category.""" diff --git a/bot/utils/cache.py b/bot/utils/cache.py index 37c2b199c..d8ec64ec8 100644 --- a/bot/utils/cache.py +++ b/bot/utils/cache.py @@ -3,7 +3,7 @@ from collections import OrderedDict  from typing import Any, Callable -def async_cache(max_size: int = 128, arg_offset: int = 0) -> Callable: +class AsyncCache:      """      LRU cache implementation for coroutines. @@ -11,23 +11,30 @@ def async_cache(max_size: int = 128, arg_offset: int = 0) -> Callable:      An offset may be optionally provided to be applied to the coroutine's arguments when creating the cache key.      """ -    # Make global cache as dictionary to allow multiple function caches -    async_cache.cache = {} - -    def decorator(function: Callable) -> Callable: -        """Define the async_cache decorator.""" -        async_cache.cache[function.__name__] = OrderedDict() - -        @functools.wraps(function) -        async def wrapper(*args) -> Any: -            """Decorator wrapper for the caching logic.""" -            key = ':'.join(str(args[arg_offset:])) - -            if key not in async_cache.cache: -                if len(async_cache.cache[function.__name__]) > max_size: -                    async_cache.cache[function.__name__].popitem(last=False) - -                async_cache.cache[function.__name__][key] = await function(*args) -            return async_cache.cache[function.__name__][key] -        return wrapper -    return decorator + +    def __init__(self): +        self._cache = OrderedDict() + +    def __call__(self, max_size: int = 128, arg_offset: int = 0) -> Callable: +        """Decorator for async cache.""" + +        def decorator(function: Callable) -> Callable: +            """Define the async cache decorator.""" + +            @functools.wraps(function) +            async def wrapper(*args) -> Any: +                """Decorator wrapper for the caching logic.""" +                key = ':'.join(str(args[arg_offset:])) + +                if key not in self._cache: +                    if len(self._cache) > max_size: +                        self._cache.popitem(last=False) + +                    self._cache[key] = await function(*args) +                return self._cache[key] +            return wrapper +        return decorator + +    def clear(self): +        """Clear cache instance.""" +        self._cache.clear()  |