From cea82da9547d3178f071241a75d024582d314ff9 Mon Sep 17 00:00:00 2001 From: Boris Muratov <8bee278@gmail.com> Date: Fri, 26 Feb 2021 14:48:10 +0200 Subject: Supressing any exceptions while updating the threshold in redis Updating redis might cause an error, making sure it doesn't stop the command mid-way --- bot/exts/moderation/defcon.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bot/exts/moderation/defcon.py b/bot/exts/moderation/defcon.py index 86dece518..a88892b13 100644 --- a/bot/exts/moderation/defcon.py +++ b/bot/exts/moderation/defcon.py @@ -2,6 +2,7 @@ import asyncio import logging import traceback from collections import namedtuple +from contextlib import suppress from datetime import datetime from enum import Enum from typing import Optional, Union @@ -208,12 +209,13 @@ class Defcon(Cog): if self.expiry is not None: self.scheduler.schedule_at(expiry, 0, self._remove_threshold()) - await self.defcon_settings.update( - { - 'threshold': Defcon._stringify_relativedelta(self.threshold) if self.threshold else "", - 'expiry': expiry.isoformat() if expiry else 0 - } - ) + with suppress(Exception): + await self.defcon_settings.update( + { + 'threshold': Defcon._stringify_relativedelta(self.threshold) if self.threshold else "", + 'expiry': expiry.isoformat() if expiry else 0 + } + ) self._update_notifier() action = Action.DURATION_UPDATE -- cgit v1.2.3 From 80153ed12d20ccaa637a55765df60d8d3b5e64ef Mon Sep 17 00:00:00 2001 From: Boris Muratov <8bee278@gmail.com> Date: Fri, 26 Feb 2021 15:17:16 +0200 Subject: Changed name of _duration_parser constant to uppercase --- bot/utils/time.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/utils/time.py b/bot/utils/time.py index a7b441327..f862e40f7 100644 --- a/bot/utils/time.py +++ b/bot/utils/time.py @@ -9,7 +9,7 @@ from dateutil.relativedelta import relativedelta RFC1123_FORMAT = "%a, %d %b %Y %H:%M:%S GMT" INFRACTION_FORMAT = "%Y-%m-%d %H:%M" -_duration_parser = re.compile( +_DURATION_REGEX = re.compile( r"((?P\d+?) ?(years|year|Y|y) ?)?" r"((?P\d+?) ?(months|month|m) ?)?" r"((?P\d+?) ?(weeks|week|W|w) ?)?" @@ -100,7 +100,7 @@ def parse_duration_string(duration: str) -> Optional[relativedelta]: The units need to be provided in descending order of magnitude. If the string does represent a durationdelta object, it will return None. """ - match = _duration_parser.fullmatch(duration) + match = _DURATION_REGEX.fullmatch(duration) if not match: return None -- cgit v1.2.3 From 6dbf8ded81716f2bf55ca4d6297e3154afcdd285 Mon Sep 17 00:00:00 2001 From: Boris Muratov <8bee278@gmail.com> Date: Fri, 26 Feb 2021 19:07:47 +0200 Subject: Sync alert won't trigger with fake redis The alert will trigger with fake redis on every bot startup even when people aren't working on the defcon cog. Added a condition to check if fake redis is being used. --- bot/exts/moderation/defcon.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/bot/exts/moderation/defcon.py b/bot/exts/moderation/defcon.py index a88892b13..aa6dc0790 100644 --- a/bot/exts/moderation/defcon.py +++ b/bot/exts/moderation/defcon.py @@ -14,7 +14,7 @@ from discord.ext import tasks from discord.ext.commands import Cog, Context, group, has_any_role from bot.bot import Bot -from bot.constants import Channels, Colours, Emojis, Event, Icons, MODERATION_ROLES, Roles +from bot.constants import Channels, Colours, Emojis, Event, Icons, MODERATION_ROLES, Redis, Roles from bot.converters import DurationDelta, Expiry from bot.exts.moderation.modlog import ModLog from bot.utils.messages import format_user @@ -89,10 +89,11 @@ class Defcon(Cog): self.expiry = datetime.fromisoformat(settings["expiry"]) if settings["expiry"] else None except Exception: log.exception("Unable to get DEFCON settings!") - await self.channel.send( - f"<@&{Roles.moderators}> <@&{Roles.devops}> **WARNING**: Unable to get DEFCON settings!" - f"\n\n```{traceback.format_exc()}```" - ) + if not Redis.use_fakeredis: + await self.channel.send( + f"<@&{Roles.moderators}> <@&{Roles.devops}> **WARNING**: Unable to get DEFCON settings!" + f"\n\n```{traceback.format_exc()}```" + ) else: if self.expiry: -- cgit v1.2.3 From 2293b9dc78d21a80043a9e9d24b9442caf7579df Mon Sep 17 00:00:00 2001 From: Boris Muratov <8bee278@gmail.com> Date: Mon, 1 Mar 2021 19:46:08 +0200 Subject: Change to handle specifically redis errors The idea to ignore alerts on fake redis didn't solve the problem completely, because sometimes you'll just develop with a real redis. It also didn't solve the ping we would get on first start up. After looking into it there seems like there's no actual reason to alert on key errors, as they should only happen if the cache gets wiped for some reason, which shouldn't happen, but in which case we have bigger issues. Alerts are therefore limited to connection errors raised by redis. This additionally handles only redis errors when writing to it as well. If any other error is raised it is ok for the function to stop at that point, as all variables have already been set. The only thing which doesn't get executed is the confirmation message and logging, the lack of which is an exception message in itself. --- bot/exts/moderation/defcon.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/bot/exts/moderation/defcon.py b/bot/exts/moderation/defcon.py index aa6dc0790..3d3f0e81e 100644 --- a/bot/exts/moderation/defcon.py +++ b/bot/exts/moderation/defcon.py @@ -2,11 +2,11 @@ import asyncio import logging import traceback from collections import namedtuple -from contextlib import suppress from datetime import datetime from enum import Enum from typing import Optional, Union +from aioredis import RedisError from async_rediscache import RedisCache from dateutil.relativedelta import relativedelta from discord import Colour, Embed, Member, User @@ -14,7 +14,7 @@ from discord.ext import tasks from discord.ext.commands import Cog, Context, group, has_any_role from bot.bot import Bot -from bot.constants import Channels, Colours, Emojis, Event, Icons, MODERATION_ROLES, Redis, Roles +from bot.constants import Channels, Colours, Emojis, Event, Icons, MODERATION_ROLES, Roles from bot.converters import DurationDelta, Expiry from bot.exts.moderation.modlog import ModLog from bot.utils.messages import format_user @@ -87,13 +87,12 @@ class Defcon(Cog): settings = await self.defcon_settings.to_dict() self.threshold = parse_duration_string(settings["threshold"]) if settings["threshold"] else None self.expiry = datetime.fromisoformat(settings["expiry"]) if settings["expiry"] else None - except Exception: + except RedisError: log.exception("Unable to get DEFCON settings!") - if not Redis.use_fakeredis: - await self.channel.send( - f"<@&{Roles.moderators}> <@&{Roles.devops}> **WARNING**: Unable to get DEFCON settings!" - f"\n\n```{traceback.format_exc()}```" - ) + await self.channel.send( + f"<@&{Roles.moderators}> <@&{Roles.devops}> **WARNING**: Unable to get DEFCON settings!" + f"\n\n```{traceback.format_exc()}```" + ) else: if self.expiry: @@ -210,14 +209,19 @@ class Defcon(Cog): if self.expiry is not None: self.scheduler.schedule_at(expiry, 0, self._remove_threshold()) - with suppress(Exception): + self._update_notifier() + + # Make sure to handle the critical part of the update before writing to Redis. + error = "" + try: await self.defcon_settings.update( { 'threshold': Defcon._stringify_relativedelta(self.threshold) if self.threshold else "", 'expiry': expiry.isoformat() if expiry else 0 } ) - self._update_notifier() + except RedisError: + error = ", but failed to write to cache" action = Action.DURATION_UPDATE @@ -234,7 +238,7 @@ class Defcon(Cog): channel_message = "removed" await self.channel.send( - f"{action.value.emoji} DEFCON threshold {channel_message}." + f"{action.value.emoji} DEFCON threshold {channel_message}{error}." ) await self._send_defcon_log(action, author) self._update_channel_topic() -- cgit v1.2.3 From b9d1de268fdaa67413e1ac4f24057cd6ecc9771d Mon Sep 17 00:00:00 2001 From: Boris Muratov <8bee278@gmail.com> Date: Mon, 1 Mar 2021 19:50:54 +0200 Subject: Provide default cache values when syncing --- bot/exts/moderation/defcon.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/exts/moderation/defcon.py b/bot/exts/moderation/defcon.py index 3d3f0e81e..482ebe13b 100644 --- a/bot/exts/moderation/defcon.py +++ b/bot/exts/moderation/defcon.py @@ -85,8 +85,8 @@ class Defcon(Cog): try: settings = await self.defcon_settings.to_dict() - self.threshold = parse_duration_string(settings["threshold"]) if settings["threshold"] else None - self.expiry = datetime.fromisoformat(settings["expiry"]) if settings["expiry"] else None + self.threshold = parse_duration_string(settings["threshold"]) if settings.get("threshold") else None + self.expiry = datetime.fromisoformat(settings["expiry"]) if settings.get("expiry") else None except RedisError: log.exception("Unable to get DEFCON settings!") await self.channel.send( -- cgit v1.2.3