diff options
author | 2023-07-08 14:27:16 +0100 | |
---|---|---|
committer | 2023-07-08 14:27:16 +0100 | |
commit | 038baa7bc0427710c8e6446967fb05751370edf3 (patch) | |
tree | 56351bc34261a0078e6820f377ddf124b1e888d6 | |
parent | Bump ruff from 0.0.275 to 0.0.277 (#2667) (diff) |
Optimise startup time (#2662)
* Defer fetching webhooks for python news until first loop, rather than startup
* Defer fetching webhook for buck pond until first duckify, rather than startup
* Use get_or_fetch channel for getting big brother channel at startup
* Defer fetching peps until first time command is ran
* Don't load extensions in a task
BotBase.load_extentions now creates a task by default, so there's no need for us to do this too.
-rw-r--r-- | bot/bot.py | 6 | ||||
-rw-r--r-- | bot/exts/fun/duck_pond.py | 15 | ||||
-rw-r--r-- | bot/exts/info/pep.py | 8 | ||||
-rw-r--r-- | bot/exts/info/python_news.py | 47 | ||||
-rw-r--r-- | bot/exts/moderation/watchchannels/_watchchannel.py | 3 |
5 files changed, 29 insertions, 50 deletions
diff --git a/bot/bot.py b/bot/bot.py index 2321232de..92ecbf130 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -2,7 +2,6 @@ import asyncio import aiohttp from pydis_core import BotBase -from pydis_core.utils import scheduling from sentry_sdk import push_scope from bot import constants, exts @@ -45,10 +44,7 @@ class Bot(BotBase): async def setup_hook(self) -> None: """Default async initialisation method for discord.py.""" await super().setup_hook() - - # This is not awaited to avoid a deadlock with any cogs that have - # wait_until_guild_available in their cog_load method. - scheduling.create_task(self.load_extensions(exts)) + await self.load_extensions(exts) async def on_error(self, event: str, *args, **kwargs) -> None: """Log errors raised in event listeners rather than printing them to stderr.""" diff --git a/bot/exts/fun/duck_pond.py b/bot/exts/fun/duck_pond.py index 63a455131..2abe72678 100644 --- a/bot/exts/fun/duck_pond.py +++ b/bot/exts/fun/duck_pond.py @@ -25,15 +25,6 @@ class DuckPond(Cog): self.ducked_messages = [] self.relay_lock = None - async def cog_load(self) -> None: - """Fetches the webhook object, so we can post to it.""" - await self.bot.wait_until_guild_available() - - try: - self.webhook = await self.bot.fetch_webhook(self.webhook_id) - except discord.HTTPException: - log.exception(f"Failed to fetch webhook with id `{self.webhook_id}`") - @staticmethod def is_staff(member: MemberOrUser) -> bool: """Check if a specific member or user is staff.""" @@ -74,6 +65,12 @@ class DuckPond(Cog): async def relay_message(self, message: Message) -> None: """Relays the message's content and attachments to the duck pond channel.""" + if not self.webhook: + await self.bot.wait_until_guild_available() + # Fetching this can fail if using an invalid webhook id. + # Letting this error bubble up is fine as it will cause an error log and sentry event. + self.webhook = await self.bot.fetch_webhook(self.webhook_id) + if message.clean_content: await send_webhook( webhook=self.webhook, diff --git a/bot/exts/info/pep.py b/bot/exts/info/pep.py index 6f50769d0..5f9a41091 100644 --- a/bot/exts/info/pep.py +++ b/bot/exts/info/pep.py @@ -29,12 +29,8 @@ class PythonEnhancementProposals(Cog): def __init__(self, bot: Bot): self.bot = bot self.peps: dict[int, str] = {} - # To avoid situations where we don't have last datetime, set this to now. - self.last_refreshed_peps: datetime = datetime.now(tz=UTC) - - async def cog_load(self) -> None: - """Carry out cog asynchronous initialisation.""" - await self.refresh_peps_urls() + # Ensure peps are refreshed the first time this is checked + self.last_refreshed_peps: datetime = datetime.min.replace(tzinfo=UTC) async def refresh_peps_urls(self) -> None: """Refresh PEP URLs listing in every 3 hours.""" diff --git a/bot/exts/info/python_news.py b/bot/exts/info/python_news.py index 76ebf2731..8507a0fec 100644 --- a/bot/exts/info/python_news.py +++ b/bot/exts/info/python_news.py @@ -40,19 +40,30 @@ class PythonNews(Cog): self.bot = bot self.webhook_names = {} self.webhook: discord.Webhook | None = None + self.fetch_new_media.start() - async def cog_load(self) -> None: - """Carry out cog asynchronous initialisation.""" - await self.get_webhook_names() - await self.get_webhook_and_channel() + async def cog_unload(self) -> None: + """Stop news posting tasks on cog unload.""" + self.fetch_new_media.cancel() - async def start_tasks(self) -> None: - """Start the tasks for fetching new PEPs and mailing list messages.""" - self.fetch_new_media.start() + async def get_webhooks(self) -> None: + """Get webhook author names from maillist API.""" + await self.bot.wait_until_guild_available() + + async with self.bot.http_session.get("https://mail.python.org/archives/api/lists") as resp: + lists = await resp.json() + + for mail in lists: + if mail["name"].split("@")[0] in constants.PythonNews.mail_lists: + self.webhook_names[mail["name"].split("@")[0]] = mail["display_name"] + self.webhook = await self.bot.fetch_webhook(constants.PythonNews.webhook) @loop(minutes=20) async def fetch_new_media(self) -> None: """Fetch new mailing list messages and then new PEPs.""" + if not self.webhook: + await self.get_webhooks() + await self.post_maillist_news() await self.post_pep_news() @@ -72,17 +83,6 @@ class PythonNews(Cog): await self.bot.api_client.put("bot/bot-settings/news", json=response) - async def get_webhook_names(self) -> None: - """Get webhook author names from maillist API.""" - await self.bot.wait_until_guild_available() - - async with self.bot.http_session.get("https://mail.python.org/archives/api/lists") as resp: - lists = await resp.json() - - for mail in lists: - if mail["name"].split("@")[0] in constants.PythonNews.mail_lists: - self.webhook_names[mail["name"].split("@")[0]] = mail["display_name"] - @staticmethod def escape_markdown(content: str) -> str: """Escape the markdown underlines and spoilers that aren't in codeblocks.""" @@ -238,17 +238,6 @@ class PythonNews(Cog): email_information = await resp.json() return thread_information, email_information - async def get_webhook_and_channel(self) -> None: - """Storage #python-news channel Webhook and `TextChannel` to `News.webhook` and `channel`.""" - await self.bot.wait_until_guild_available() - self.webhook = await self.bot.fetch_webhook(constants.PythonNews.webhook) - - await self.start_tasks() - - async def cog_unload(self) -> None: - """Stop news posting tasks on cog unload.""" - self.fetch_new_media.cancel() - async def setup(bot: Bot) -> None: """Add `News` cog.""" diff --git a/bot/exts/moderation/watchchannels/_watchchannel.py b/bot/exts/moderation/watchchannels/_watchchannel.py index c3f823982..5250e64d9 100644 --- a/bot/exts/moderation/watchchannels/_watchchannel.py +++ b/bot/exts/moderation/watchchannels/_watchchannel.py @@ -20,6 +20,7 @@ from bot.exts.moderation.modlog import ModLog from bot.log import CustomLogger, get_logger from bot.pagination import LinePaginator from bot.utils import CogABCMeta, messages, time +from bot.utils.channel import get_or_fetch_channel from bot.utils.members import get_or_fetch_member log = get_logger(__name__) @@ -97,7 +98,7 @@ class WatchChannel(metaclass=CogABCMeta): await self.bot.wait_until_guild_available() try: - self.channel = await self.bot.fetch_channel(self.destination) + self.channel = await get_or_fetch_channel(self.destination) except HTTPException: self.log.exception(f"Failed to retrieve the text channel with id `{self.destination}`") |