WechatOnCloud/bridge/woc_bridge/models/base.py
Kris ed2ee086de refactor: 重构UI操作调度,引入优先级调度与监控
主要变更:
1. 新增UIActionScheduler实现优先级UI任务调度,支持CRITICAL/HIGH/NORMAL/LOW四级优先级
2. 替换原有SendQueue为UIActionScheduler,统一所有UI操作的调度逻辑
3. 为截图、登录、重启等API添加调度器封装,支持超时、限流与fast-fail机制
4. 新增Prometheus监控指标,统计UI任务执行、等待耗时、超时、限流与快速失败情况
5. 为QrCapture添加命令执行超时保护,避免X11操作卡死
6. 扩展StatusResponse与状态接口,暴露调度器指标
7. 新增完整的单元测试覆盖调度器功能
8. 为看门狗注入调度器,实现kill前队列清空与快速失败窗口
2026-07-18 03:43:28 +08:00

79 lines
2.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""基础模型:错误码 / BridgeError 异常 / ErrorResponse。"""
from __future__ import annotations
from typing import Any, Optional
from pydantic import BaseModel, Field
# ---------------------------------------------------------------------------
# 错误码定义(与 spec 一致)
# ---------------------------------------------------------------------------
# 每个错误码对应一个 HTTP 状态码
ERROR_CODES: dict[str, int] = {
"WECHAT_NOT_RUNNING": 503,
"WECHAT_NOT_LOGGED_IN": 401,
"WINDOW_NOT_FOUND": 503,
"CONTACT_NOT_FOUND": 404,
"SEND_FAILED": 500,
"DB_LOCKED": 503,
"DB_NOT_FOUND": 500,
"INVALID_PARAMS": 400,
"BRIDGE_INTERNAL_ERROR": 500,
"LOGIN_TIMEOUT": 408,
"MEDIA_NOT_FOUND": 404,
"RATE_LIMITED": 429,
"DB_ENCRYPTED": 503,
"DB_NEED_INIT": 503,
"DB_INIT_IN_PROGRESS": 503,
"DB_KEY_INVALID": 503,
"LOGOUT_FAILED": 500,
"RESTART_TIMEOUT": 408,
"REVOKE_WINDOW_EXPIRED": 409,
# UI 自动化 Flow 错误码P3
"SEND_TIMEOUT": 503,
"STATE_DIRTY": 503,
"X11_TEMP_UNAVAILABLE": 503,
"X11_UNAVAILABLE": 503,
"ELEMENT_NOT_FOUND": 503,
"DB_VERIFY_FAILED": 500,
"AMBIGUOUS_CONTACT": 400,
"BRIDGE_CIRCUITED": 503,
"WECHAT_NOT_READY": 503,
}
class BridgeError(Exception):
"""bridge 统一业务异常。
路由层直接 raise BridgeError(code="...", message="...", details=...)
由全局异常处理器捕获后转换为统一 ErrorResponse 并设置对应 HTTP 状态码。
"""
def __init__(
self,
code: str = "BRIDGE_INTERNAL_ERROR",
message: str = "bridge internal error",
http_status: Optional[int] = None,
details: Optional[Any] = None,
) -> None:
self.code = code
self.message = message
# 若未显式指定 http_status则查表取默认值查不到则回落到 500
self.http_status = http_status if http_status is not None else ERROR_CODES.get(code, 500)
self.details = details
super().__init__(f"[{code}] {message}")
# ---------------------------------------------------------------------------
# 通用错误响应
# ---------------------------------------------------------------------------
class ErrorResponse(BaseModel):
"""统一错误响应结构。"""
success: bool = Field(default=False, description="固定为 false")
error: dict[str, Any] = Field(
description="错误详情,含 code/message/details 三个字段"
)