主要变更: 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前队列清空与快速失败窗口
61 lines
2.2 KiB
Python
61 lines
2.2 KiB
Python
from __future__ import annotations
|
||
|
||
import logging
|
||
|
||
from fastapi import APIRouter
|
||
from fastapi.responses import Response
|
||
|
||
from woc_bridge.config import _require_qr_capture, _require_send_queue
|
||
from woc_bridge.messaging.ui_action_scheduler import Priority
|
||
from woc_bridge.models import BridgeError
|
||
|
||
logger = logging.getLogger("woc-bridge")
|
||
router = APIRouter()
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 路由:POST /api/screenshot
|
||
# ---------------------------------------------------------------------------
|
||
@router.post("/api/screenshot")
|
||
async def screenshot() -> Response:
|
||
"""截取完整屏幕并返回 PNG。
|
||
|
||
用于前端「截图」按钮 / 调试时观察微信实际界面状态(如确认 UI 操作是否
|
||
触发了正确的对话框)。截取整个 X 桌面(DISPLAY 由 _state.config.display 指定)。
|
||
|
||
Returns:
|
||
Response:Content-Type=image/png,body 为 PNG 二进制
|
||
|
||
Raises:
|
||
BridgeError(WINDOW_NOT_FOUND): X 会话未就绪,无法截图(HTTP 503)
|
||
其他异常由全局兜底处理器返回 BRIDGE_INTERNAL_ERROR
|
||
|
||
Notes:
|
||
- 截图由 qr_capture.capture_full_screenshot 完成,底层调
|
||
xdotool/getwindowgeometry + import(ImageMagick)
|
||
- 与 /api/login/qr/start 区别:本接口截全屏,qr/start 截二维码区域
|
||
- 大屏幕截图可能 > 1MB,调用方注意带宽
|
||
"""
|
||
logger.info("screenshot: 收到请求")
|
||
qr_capture = _require_qr_capture()
|
||
scheduler = _require_send_queue()
|
||
|
||
try:
|
||
if hasattr(scheduler, "execute"):
|
||
png_bytes = await scheduler.execute(
|
||
lambda: qr_capture.capture_full_screenshot(),
|
||
priority=Priority.LOW,
|
||
wait_timeout_ms=10000,
|
||
trace_id="screenshot",
|
||
)
|
||
else:
|
||
png_bytes = await qr_capture.capture_full_screenshot()
|
||
except BridgeError as e:
|
||
logger.warning("screenshot: 失败 %s: %s", e.code, e.message)
|
||
raise
|
||
except Exception as e:
|
||
logger.warning("screenshot: 失败 %s: %s", type(e).__name__, e)
|
||
raise
|
||
logger.info("screenshot: ✓ 截图成功 %d bytes", len(png_bytes))
|
||
return Response(content=png_bytes, media_type="image/png")
|