diff options
| author | 2020-11-14 23:07:13 +0100 | |
|---|---|---|
| committer | 2020-11-15 03:12:58 +0100 | |
| commit | 07a5d5fc58a402f930505c7b29a7a275e743a84d (patch) | |
| tree | 030529317ac5e3eef69e5b7499f534bf7570d061 | |
| parent | Rework the doc redis cache to work with hashes (diff) | |
Update existing redis values when parsing pages
If we're parsing a page for a symbol that's out of the cache
and encounter a symbol that was already cached we can update that symbol
to keep it up to date without additional requests
| -rw-r--r-- | bot/exts/info/doc/_cog.py | 14 | ||||
| -rw-r--r-- | bot/exts/info/doc/_redis_cache.py | 17 |
2 files changed, 25 insertions, 6 deletions
diff --git a/bot/exts/info/doc/_cog.py b/bot/exts/info/doc/_cog.py index 67a21ed72..678134f3c 100644 --- a/bot/exts/info/doc/_cog.py +++ b/bot/exts/info/doc/_cog.py @@ -36,6 +36,8 @@ FORCE_PREFIX_GROUPS = ( WHITESPACE_AFTER_NEWLINES_RE = re.compile(r"(?<=\n\n)(\s+)") NOT_FOUND_DELETE_DELAY = RedirectOutput.delete_delay +doc_cache = DocRedisCache(namespace="Docs") + class DocItem(NamedTuple): """Holds inventory symbol information.""" @@ -116,7 +118,9 @@ class CachedParser: while self._queue: item, soup = self._queue.pop() try: - self._results[item] = get_symbol_markdown(soup, item) + markdown = get_symbol_markdown(soup, item) + await doc_cache.set_if_exists(item, markdown) + self._results[item] = markdown except Exception: log.exception(f"Unexpected error when handling {item}") else: @@ -161,8 +165,6 @@ class CachedParser: class DocCog(commands.Cog): """A set of commands for querying & displaying documentation.""" - doc_cache = DocRedisCache() - def __init__(self, bot: Bot): self.base_urls = {} self.bot = bot @@ -174,7 +176,7 @@ class DocCog(commands.Cog): self.scheduled_inventories = set() self.bot.loop.create_task(self.init_refresh_inventory()) - self.bot.loop.create_task(self.doc_cache.delete_expired()) + self.bot.loop.create_task(doc_cache.delete_expired()) async def init_refresh_inventory(self) -> None: """Refresh documentation inventory on cog initialization.""" @@ -292,12 +294,12 @@ class DocCog(commands.Cog): return None self.bot.stats.incr(f"doc_fetches.{symbol_info.package.lower()}") - markdown = await self.doc_cache.get(symbol_info) + markdown = await doc_cache.get(symbol_info) if markdown is None: log.debug(f"Redis cache miss for symbol `{symbol}`.") markdown = await self.item_fetcher.get_markdown(self.bot.http_session, symbol_info) if markdown is not None: - await self.doc_cache.set(symbol_info, markdown) + await doc_cache.set(symbol_info, markdown) else: markdown = "Unable to parse the requested symbol." diff --git a/bot/exts/info/doc/_redis_cache.py b/bot/exts/info/doc/_redis_cache.py index c617eba49..2230884c9 100644 --- a/bot/exts/info/doc/_redis_cache.py +++ b/bot/exts/info/doc/_redis_cache.py @@ -28,6 +28,23 @@ class DocRedisCache(RedisObject): ) @namespace_lock + async def set_if_exists(self, item: DocItem, value: str) -> None: + """ + Set markdown `value` for `key` if `key` exists. + + Keys expire after a week to keep data up to date. + """ + expiry_timestamp = datetime.datetime.now().timestamp() + 7 * 24 * 60 * 60 + + with await self._get_pool_connection() as connection: + if await connection.hexists(f"{self.namespace}:{item.package}", self.get_item_key(item)): + await connection.hset( + f"{self.namespace}:{item.package}", + self.get_item_key(item), + pickle.dumps((value, expiry_timestamp)) + ) + + @namespace_lock async def get(self, item: DocItem) -> Optional[str]: """Get markdown contents for `key`.""" with await self._get_pool_connection() as connection: |