feat: add retry capabilities to the bot

This commit is contained in:
cătălin 2025-03-06 18:10:35 +01:00
commit e891d6fc1d
No known key found for this signature in database
3 changed files with 64 additions and 8 deletions

View file

@ -5,6 +5,12 @@ from enum import StrEnum
from typing import ClassVar
from loguru import logger
from tenacity import (
retry,
retry_if_exception_type,
stop_after_attempt,
wait_exponential,
)
from twitchio import Channel
from twitchio.ext import commands, routines
@ -64,6 +70,8 @@ class Bot(commands.Bot):
)
return
await ctx.send(sentence)
# Wait for the specified time
await asyncio.sleep(60)
@commands.command(aliases=["qadd"])
async def add_quote(self, ctx: commands.Context, *, quote: str):
@ -134,7 +142,7 @@ class HelloMessagesCog(commands.Cog):
if message.content in self.hello_patterns:
hello = self.hello_svc.run(message.author.name)
if hello:
await message.channel_name.send(hello)
await message.channel.send(hello)
class MessageType(StrEnum):
@ -181,12 +189,10 @@ class MessageHandler:
class SaveMessagesCog(commands.Cog):
def __init__(self, bot):
def __init__(self, bot: Bot):
self.bot = bot
self.store_svc = SentenceStorerSvc(db=MarkovDatabase(channel=bot.channel_name))
self.generate_svc = SentenceGeneratorSvc(
db=MarkovDatabase(channel=bot.channel_name)
)
self.store_svc = SentenceStorerSvc(db=MarkovDatabase(channel=bot.channel))
self.generate_svc = SentenceGeneratorSvc(db=MarkovDatabase(channel=bot.channel))
self.backoff_svc = BackoffService()
self.message_handler = MessageHandler(self._send_message)
@ -204,7 +210,7 @@ class SaveMessagesCog(commands.Cog):
async def typed_send(content: str):
if hasattr(self, "current_message"):
await self.current_message.channel_name.send(content)
await self.current_message.channel.send(content)
# Set a unique name for the function to ensure it's treated as distinct
typed_send.__name__ = f"send_{type_name}"
@ -213,7 +219,7 @@ class SaveMessagesCog(commands.Cog):
async def _send_message(self, content: str):
"""Generic send message function (for non-backoff uses)"""
if hasattr(self, "current_message"):
await self.current_message.channel_name.send(content)
await self.current_message.channel.send(content)
@commands.Cog.event()
async def event_message(self, message):
@ -266,6 +272,43 @@ class BotsManager:
self.bots[user.username] = bot
async def run_user_bot(self, user: User):
if user.username not in self.bots:
return None
logger.info(f"Starting bot for {user.username}")
bot = self.bots[user.username]
@retry(
stop=stop_after_attempt(5),
wait=wait_exponential(multiplier=2, min=2, max=60),
retry=retry_if_exception_type((ConnectionError, TimeoutError, OSError)),
)
async def start_bot_with_retry():
await bot.start()
task = asyncio.create_task(start_bot_with_retry())
def on_bot_done(future):
try:
if future.cancelled():
logger.warning(f"Bot for {user.username} was cancelled")
elif future.exception():
logger.error(
f"Bot for {user.username} failed: {future.exception()}"
)
else:
logger.info(f"Bot for {user.username} stopped normally")
except Exception as e: # noqa: BLE001
logger.error(f"Error in bot completion callback: {e}")
task.add_done_callback(on_bot_done)
bot.start_routines()
return task
async def run_user_bot2(self, user: User):
if user.username not in self.bots:
return
@ -275,6 +318,7 @@ class BotsManager:
task.add_done_callback(
lambda x: logger.info(f"Bot for {user.username} stopped")
)
bot.start_routines()
async def stop_user_bot(self, user: User):