diff --git a/bot/src/cogs/galtinn.py b/bot/src/cogs/galtinn.py index 2d51053..4797000 100644 --- a/bot/src/cogs/galtinn.py +++ b/bot/src/cogs/galtinn.py @@ -402,6 +402,7 @@ class Galtinn(commands.Cog): return success @tasks.loop(time=misc_utils.MIDNIGHT) + @misc_utils.log_errors async def membership_check(self): """ Checks all registered user's membership status and assigns roles based on the status @@ -463,6 +464,7 @@ class Galtinn(commands.Cog): await self.bot.wait_until_ready() @tasks.loop(minutes=2) + @misc_utils.log_errors async def verification_cleanup(self): """ Clean up any pending verifications that have expired diff --git a/bot/src/cogs/utils/misc_utils.py b/bot/src/cogs/utils/misc_utils.py index 12e8e07..6a246c9 100644 --- a/bot/src/cogs/utils/misc_utils.py +++ b/bot/src/cogs/utils/misc_utils.py @@ -1,9 +1,46 @@ +import asyncio import datetime +import functools from math import ceil from zoneinfo import ZoneInfo +import aiohttp +import discord + MIDNIGHT = datetime.time(hour=0, minute=0, tzinfo=ZoneInfo("Europe/Oslo")) +# The exceptions discord.py's tasks.loop retries instead of stopping on +RETRIED_TASK_EXCEPTIONS = ( + OSError, + discord.GatewayNotFound, + discord.ConnectionClosed, + aiohttp.ClientError, + asyncio.TimeoutError, +) + + +def log_errors(func): + """ + Decorator for background task loops that logs exceptions instead of letting them stop the loop. + Network errors are re-raised so discord.py can retry the iteration like it normally does. + Put it below the @tasks.loop decorator. The decorated method's class needs a `bot` attribute + + Parameters + ---------- + func (callable): The loop's coroutine function + """ + + @functools.wraps(func) + async def wrapper(self, *args, **kwargs): + try: + await func(self, *args, **kwargs) + except RETRIED_TASK_EXCEPTIONS: + raise + except Exception: + self.bot.logger.exception(f"Unhandled error in background task {func.__qualname__}") + + return wrapper + class Paginator: """Interface for managing content. Divides your content into pages of 10 items each"""