生产是 `gunicorn -w 2`,两个进程各自跑 lifespan,start_all() 会把同一个通道的 长轮询拉两遍:消息被其中一个消费、回复从另一个发出,游标还会互相覆盖。 改成 Postgres 会话级 advisory lock 做租约:抢到的进程收消息,另一个每 10 秒重试, 主进程一挂连接断、锁释放,备用进程立刻接上。页面上的"接收中"只认抢到租约的那个 (`manager.polling()`),不再把等锁的也算进去。 补测试 `test_only_one_process_holds_the_polling_lease`: 第一个抢到、第二个抢不到、第一个放手后第三个能接上。
This commit is contained in:
@@ -66,7 +66,8 @@ def _channel_out(channel: BotChannel) -> dict[str, Any]:
|
||||
"name": channel.name,
|
||||
"status": channel.status,
|
||||
"connected": bool(channel.bot_token_enc) and channel.status == "active",
|
||||
"polling": manager.running(channel.id),
|
||||
# 只有抢到租约、真在拉消息的进程才算"接收中";备用进程的任务在等键,不算。
|
||||
"polling": manager.polling(channel.id),
|
||||
"ilink_user_id": channel.ilink_user_id,
|
||||
"last_seen_at": channel.last_seen_at,
|
||||
"last_error": channel.last_error,
|
||||
|
||||
Reference in New Issue
Block a user