From e8b110d12e183c4b9ff1fac63bb509d910d0ccd7 Mon Sep 17 00:00:00 2001 From: Bast Date: Sat, 22 May 2021 13:17:02 -0700 Subject: Fix infraction rescheduler breaking with more than 100 in flight reactions Make sure to only fetch infractions to reschedule by filtering by type and permanent status. We don't reschedule permanents as they will never be automatically expired, so they're a waste and clog to filter out manually. There is a PR for `site` to add the requisite filters (`types` and `permanent`). We also only reschedule the soonest-expiring infractions, waiting until we've processed all of them before fetching the next batch by ordering them by expiration time. --- bot/exts/moderation/infraction/_scheduler.py | 29 ++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 988fb7220..c94874787 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -48,11 +48,32 @@ class InfractionScheduler: infractions = await self.bot.api_client.get( 'bot/infractions', - params={'active': 'true'} + params={ + 'active': 'true', + 'ordering': 'expires_at', + 'permanent': 'false', + 'types': ','.join(supported_infractions), + }, ) - for infraction in infractions: - if infraction["expires_at"] is not None and infraction["type"] in supported_infractions: - self.schedule_expiration(infraction) + + to_schedule = [i for i in infractions if not i['id'] in self.scheduler] + + for infraction in to_schedule: + log.trace("Scheduling %r", infraction) + self.schedule_expiration(infraction) + + # Call ourselves again when the last infraction would expire. This will be the "oldest" infraction we've seen + # from the database so far, and new ones are scheduled as part of application. + # We make sure to fire this + if to_schedule: + next_reschedule_point = max( + dateutil.parser.isoparse(infr["expires_at"]).replace(tzinfo=None) for infr in to_schedule + ) + log.trace("Will reschedule remaining infractions at %s", next_reschedule_point) + + self.scheduler.schedule_at(next_reschedule_point, -1, self.reschedule_infractions(supported_infractions)) + + log.trace("Done rescheduling") async def reapply_infraction( self, -- cgit v1.2.3