feat(bot): ✨ Move messages flushing to a separate process.
This commit is contained in:
@@ -30,11 +30,6 @@ class Calls(base.Cog):
|
||||
self.hangup_calls.add_exception_type(exceptions.ConfigurationError)
|
||||
# self.hangup_calls.start()
|
||||
|
||||
self.flush_messages.add_exception_type(exceptions.ConfigurationError)
|
||||
self.flush_messages.add_exception_type(TypeError)
|
||||
self.flush_messages.add_exception_type(RuntimeError)
|
||||
self.flush_messages.start()
|
||||
|
||||
def cog_unload(self) -> None:
|
||||
self.hangup_calls.cancel()
|
||||
|
||||
@@ -86,89 +81,6 @@ class Calls(base.Cog):
|
||||
await models.Channel.filter(id__in=hung_up_channel_ids).update(call_id=None)
|
||||
await redis.srem(constants.CHANNELS_ONCALL_SET, *hung_up_channel_ids)
|
||||
|
||||
@tasks.loop(seconds=15)
|
||||
async def flush_messages(self, all_calls: bool = False) -> None:
|
||||
"""Fetches all the pending messages from Redis and flushes them to the DB.
|
||||
|
||||
Args:
|
||||
all_calls (bool, optional): Whether to flush the messages for all calls of all shards.
|
||||
"""
|
||||
|
||||
call_ids = await redis.smembers(constants.CALL_IDS_TO_FLUSH)
|
||||
|
||||
# Redis returns bytes.
|
||||
call_ids = [
|
||||
int(call_id)
|
||||
for call_id in call_ids
|
||||
if all_calls
|
||||
or (int(call_id) % self.bot.shard_count) - self.bot.shard_ids[0] == 0
|
||||
]
|
||||
|
||||
if len(call_ids) == 0:
|
||||
return
|
||||
|
||||
await redis.srem(constants.CALL_IDS_TO_FLUSH, *call_ids)
|
||||
|
||||
pipe = redis.pipeline()
|
||||
|
||||
for call_id in call_ids:
|
||||
pipe.hgetall(constants.CALL_MESSAGES_TEMPLATE % call_id)
|
||||
pipe.hgetall(constants.CALL_MESSAGE_CONTENTS_TEMPLATE % call_id)
|
||||
|
||||
for call_id, (messages, message_contents) in zip(
|
||||
call_ids, utils.chunks(await pipe.execute(), 2)
|
||||
):
|
||||
message_rows: list[models.Message] = []
|
||||
|
||||
for message_json in messages.values():
|
||||
message_rows.append(models.Message(**orjson.loads(message_json)))
|
||||
|
||||
message_content_rows: list[models.MessageContent] = []
|
||||
|
||||
for message_content_json in message_contents.values():
|
||||
message_content_rows.append(
|
||||
models.MessageContent(**orjson.loads(message_content_json))
|
||||
)
|
||||
|
||||
message_rows.sort(key=lambda m: m.id)
|
||||
message_content_rows.sort(key=lambda mc: mc.message_id)
|
||||
|
||||
pipe = redis.pipeline()
|
||||
|
||||
pipe.delete(
|
||||
constants.CALL_MESSAGE_CONTENT_ITERATIONS_TEMPLATE % call_id,
|
||||
constants.CALL_MESSAGE_CONTENTS_TEMPLATE % call_id,
|
||||
constants.CALL_MESSAGE_FROM_PROPAGATION_TEMPLATE % call_id,
|
||||
constants.CALL_MESSAGES_TEMPLATE % call_id,
|
||||
constants.CALL_MESSAGE_REPLIES_TEMPLATE % call_id,
|
||||
)
|
||||
|
||||
await pipe.execute()
|
||||
|
||||
for _ in range(3):
|
||||
try:
|
||||
await models.Message.bulk_create(message_rows, batch_size=20)
|
||||
break
|
||||
|
||||
except (
|
||||
asyncpg.exceptions.PostgresError,
|
||||
asyncpg.exceptions.InterfaceError,
|
||||
):
|
||||
continue
|
||||
|
||||
for _ in range(3):
|
||||
try:
|
||||
await models.MessageContent.bulk_create(
|
||||
message_content_rows, batch_size=20
|
||||
)
|
||||
break
|
||||
|
||||
except (
|
||||
asyncpg.exceptions.PostgresError,
|
||||
asyncpg.exceptions.InterfaceError,
|
||||
):
|
||||
continue
|
||||
|
||||
@commands.command(aliases=["c"])
|
||||
@commands.guild_only()
|
||||
@checks.is_unbanned()
|
||||
|
||||
Reference in New Issue
Block a user