fix(avatar): fail closed on BOXIM connection errors

This commit is contained in:
stefanfeng
2026-08-20 14:47:13 +08:00
parent 08590bf9ea
commit 51a317ccd9
7 changed files with 173 additions and 17 deletions
@@ -97,7 +97,18 @@ class BoxIMClient:
payload.get("message") or "BOXIM 授权失败",
code=code or response.status_code,
auth_error=response.status_code in (400, 401, 403)
or code in (400, 401, 40100, 403, "400", "401", "40100", "403"),
or code in (
400,
401,
40100,
40101,
403,
"400",
"401",
"40100",
"40101",
"403",
),
)
if not data.get("accessToken"):
raise BoxIMError("会会未返回 BOXIM 访问凭证", auth_error=True)
@@ -128,7 +139,7 @@ class BoxIMClient:
payload.get("message") or "BOXIM 请求失败",
code=code or response.status_code,
auth_error=response.status_code in (400, 401, 403)
or code in (400, 401, 403, "400", "401", "403"),
or code in (400, 401, 40100, 40101, 403, "400", "401", "40100", "40101", "403"),
)
return payload.get("data")
@@ -191,6 +191,37 @@ class TakeoverService:
def _forget_boxim_session(self, user_id: str):
self._sessions.pop(user_id, None)
def _disable_after_connection_failure(
self,
db: Session,
avatar: Avatar,
cursor: TakeoverCursor,
message: str,
):
permissions = (avatar.config or {}).get("authorizationPermissions", [])
avatar.config = {
**(avatar.config or {}),
"authorizationPermissions": [
permission
for permission in permissions
if permission != TAKEOVER_PERMISSION
],
}
cursor.last_error = message
cursor.last_polled_at = self.now()
tasks = (
db.query(TakeoverReplyTask)
.filter(
TakeoverReplyTask.avatar_id == avatar.id,
TakeoverReplyTask.status.in_(ACTIVE_TASK_STATUSES),
)
.all()
)
for task in tasks:
task.status = "cancelled"
task.cancel_reason = "connection_failed"
task.locked_at = None
async def _sync_avatar(self, avatar_id: str) -> bool:
db = self.session_factory()
try:
@@ -204,8 +235,12 @@ class TakeoverService:
db.add(cursor)
db.flush()
if not user or not user.huihui_token:
cursor.last_error = "请重新登录会会生产账号后再开启主动接管"
cursor.last_polled_at = self.now()
self._disable_after_connection_failure(
db,
avatar,
cursor,
"请重新登录会会生产账号后再开启主动接管",
)
db.commit()
return False
@@ -222,10 +257,10 @@ class TakeoverService:
except Exception as exc:
if isinstance(exc, BoxIMError) and exc.auth_error:
self._forget_boxim_session(user.id)
cursor.last_error = "BOXIM 授权已失效,请重新登录会会生产账号"
message = "BOXIM 授权已失效,请重新登录会会生产账号"
else:
cursor.last_error = f"BOXIM 暂时连接失败:{str(exc)[:160]}"
cursor.last_polled_at = self.now()
message = f"BOXIM 暂时连接失败:{str(exc)[:160]}"
self._disable_after_connection_failure(db, avatar, cursor, message)
db.commit()
logger.warning("BOXIM sync failed for avatar %s: %s", avatar.id, exc)
return False