【发布时间】:2022-08-21 22:11:22
【问题描述】:
我正在开发一个 Twitch Bot 大约一年。随着时间的推移,机器人变得越来越大以添加功能。现在,该机器人可以管理多个接口,包括 Discord、Twitch、Twitch API、Streamlabs ......并拥有一个 Web 界面来接收来自 OAuth 身份验证 API 的所有回调,并将 HTML 页面上的一些统计信息呈现给流媒体。
然而,机器人越大,我遇到的问题就越多。事实是,我不认为我当前的架构是好的。这就是它目前的做法:
首先,我实例化一个Core 类,该类将包含所有机器人和接口的实例,并存储它们之间共享的变量。它还包含数据库的全局异步锁(由于整个机器人在单个异步循环上运行,我需要确保只有一个接口同时与数据库通信)。
class Core:
def __init__(self):
# Define session lock for database access
self.session_lock: asyncio.locks.Lock = asyncio.Lock()
# Store bots & API access
self.discord_bot: Optional[discord.Client] = None
self.twitch_bot: Optional[twitchio.ext.commands.Bot] = None # Manage Twitch IRC chat
self.twitch_api: TwitchApi = None # Manage Twitch API
# Other interfaces ...
# Some shared attributes which are read by all interfaces ...
然后,我通过传递核心来实例化我的所有接口。每个接口在实例化时都会自行注册到内核中。这是接口初始化的示例(此处为 Discord):
class DiscordBot(commands.Bot):
def __init__(self, core: Core, **options):
super().__init__(**options)
self.core: Core = core
self.core.discord_bot = self
我的主脚本中的实例化阶段:
core = Core()
discord_bot = DiscordBot(core)
twitch_bot = TwitchChatBot(core, os.environ[\'TWITCH_BOT_TMI_TOKEN\'], [os.environ[\'TWITCH_CHANNEL_NAME\']])
loop = asyncio.get_event_loop()
loop.create_task(twitch_bot.connect())
loop.create_task(discord_bot.start(os.environ[\"DISCORD_BOT_TOKEN\"]))
loop.run_forever()
这是我的架构的全局图及其管理方式:
这种架构非常方便,因为它允许我在接口之间建立一个非常简单的桥梁。例如,如果我想通过我的 Twitch 机器人在 Discord 上发布消息,我只需拨打 self.core.discord_bot.get_channel(...).send()。另一个方向也一样。
但我觉得这种架构不再可持续。目前Core 类包含超过5000 行代码和60 多个在所有接口之间共享的方法。我想在多个文件中分解它,但它是一团糟。此外,我越来越认为从长远来看,在同一个异步循环上运行所有接口并不是一个好主意。
我想到了解决方案,比如将所有接口分成不同的进程。但是,如何在不做复杂事情的情况下管理这些进程之间的同步(我以 Twitch bot 在 Discord 上发布消息为例)。我还查看了 Redis 之类的同步解决方案,但我真的不知道它是否可以回答我所有的问题......我还考虑过使用 python 导入模块直接导入 Core 实例(因此不必注册每个界面中的核心),但我不确定它是否会起作用以及它是否是一个好习惯。
我再举一个例子,在Core 类中实例化了一个处理机器人和社区之间交互的类。它用于改变与用户的交互(一种原始聊天机器人)。这个类必须在我的所有界面之间共享,因为我希望 Discord 机器人的反应根据 Twitch 上发生的事情做出反应。
无论如何,我想听听您对此的专家意见。你会如何组织这一切? 谢谢 :)
标签: python design-patterns architecture bots