From 4f54f2d058c6ab7ff937648884c5fdf7e847f898 Mon Sep 17 00:00:00 2001 From: osmarks Date: Thu, 15 Apr 2021 13:15:17 +0100 Subject: [PATCH] fix concurrency issue by serializing role transfers --- src/esoserver.py | 30 ++++++++++++++++++------------ src/metrics.py | 1 + 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/esoserver.py b/src/esoserver.py index 6c4a2dd..4bdbc60 100644 --- a/src/esoserver.py +++ b/src/esoserver.py @@ -2,22 +2,28 @@ import util import random import logging import discord +import asyncio import metrics +role_transfer_lock = asyncio.Lock() + def setup(bot): @bot.listen() async def on_message(message): if message.guild.id == util.config["esoserver"]["id"]: - for role in message.role_mentions: - if role.id == util.config["esoserver"]["transfer_role"]: # transfer the role from sender to other pinged person - if len(message.mentions) == 1: - await message.author.remove_roles(role, reason="untransfer unrole") - await message.mentions[0].add_roles(role, reason="transfer role") - return - for user in message.mentions: - for role in user.roles: - if role.id == util.config["esoserver"]["transfer_role"]: # transfer from pingee to pinger - await user.remove_roles(role, reason="untransfer unrole") - await message.author.add_roles(role, reason="transfer role") - return \ No newline at end of file + async with role_transfer_lock: # prevent concurrency horrors - serialize accesses, probably + for role in message.role_mentions: + if role.id == util.config["esoserver"]["transfer_role"]: # transfer the role from sender to other pinged person + if len(message.mentions) == 1: + await message.author.remove_roles(role, reason="untransfer unrole") + await message.mentions[0].add_roles(role, reason="transfer role") + metrics.role_transfers.inc() + return + for user in message.mentions: + for role in user.roles: + if role.id == util.config["esoserver"]["transfer_role"]: # transfer from pingee to pinger + await user.remove_roles(role, reason="untransfer unrole") + await message.author.add_roles(role, reason="transfer role") + metrics.role_transfers.inc() + return \ No newline at end of file diff --git a/src/metrics.py b/src/metrics.py index 613d86e..c22662c 100644 --- a/src/metrics.py +++ b/src/metrics.py @@ -2,3 +2,4 @@ import prometheus_client achievements_achieved = prometheus_client.Counter("abr_achievements", "Achievements achieved by users") reminders_fired = prometheus_client.Counter("abr_reminders", "Reminders successfully delivered to users") +role_transfers = prometheus_client.Counter("abr_role_transfers", "Times the esoserver transferable role has been transferred") \ No newline at end of file