上一版把双进程抢会话修了,但生产重启后仍然不收消息:`start_all()` 是进程启动时的
查询,那一刻没有工作区上下文,`bot_channel` 的 RLS 把行全藏起来,一行都查不到,
于是"页面上显示已连接,实际上没人在拉消息"。
- 迁移 0016 补一条只读策略:`current_setting('app.bot_list') = 'on'` 时允许 SELECT
(只开 SELECT,防止顺手拿它改别人的通道);
- `start_all()` 走 `active_channel_ids()`,先设这个 GUC 再列通道;
- 补测试 `test_startup_sees_logged_in_channels`。
This commit is contained in:
@@ -54,6 +54,23 @@ def site_base() -> str:
|
||||
return ""
|
||||
|
||||
|
||||
async def active_channel_ids() -> list[uuid.UUID]:
|
||||
"""列出"已扫码登录、该收消息"的通道。
|
||||
|
||||
启动时还没有工作区上下文,`bot_channel` 的 RLS 会把行全藏起来,所以先设
|
||||
`app.bot_list='on'` 走迁移 0016 那条只读口子——不设的话重启后机器人会静默失联。
|
||||
"""
|
||||
async with SessionFactory() as session, session.begin():
|
||||
await session.execute(sa_text("SELECT set_config('app.bot_list', 'on', true)"))
|
||||
rows = await session.execute(
|
||||
select(BotChannel.id).where(
|
||||
BotChannel.status == "active",
|
||||
BotChannel.bot_token_enc.is_not(None),
|
||||
)
|
||||
)
|
||||
return [row[0] for row in rows]
|
||||
|
||||
|
||||
async def acquire_lease(channel_id: uuid.UUID):
|
||||
"""抢"这个通道由我收消息"的租约;抢到返回连接(关掉就是释放),抢不到返回 None。
|
||||
|
||||
@@ -103,14 +120,7 @@ class BotManager:
|
||||
|
||||
async def start_all(self) -> None:
|
||||
"""进程启动时把已登录的通道都拉起来,不然重启就静默不收消息了。"""
|
||||
async with SessionFactory() as session:
|
||||
rows = await session.execute(
|
||||
select(BotChannel.id).where(
|
||||
BotChannel.status == "active",
|
||||
BotChannel.bot_token_enc.is_not(None),
|
||||
)
|
||||
)
|
||||
ids = [row[0] for row in rows]
|
||||
ids = await active_channel_ids()
|
||||
for channel_id in ids:
|
||||
await self.start(channel_id)
|
||||
if ids:
|
||||
|
||||
Reference in New Issue
Block a user