From 445c16c32989c422ed78e6a9ed059aecd69567d7 Mon Sep 17 00:00:00 2001 From: snowy-yang <102860110+snowy-yang@users.noreply.github.com> Date: Sat, 26 Sep 2026 18:54:04 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20web/routers/tasks.py=20=E7=9A=84=20?= =?UTF-8?q?=5Ftouch=5Fdevice=20=E6=94=B6=E6=95=9B=E5=88=B0=20services=20?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为什么:_touch_device 在 services/tasks.py 与 web/routers/tasks.py 各有一份 逐字相同的实现,且两份都活着。同一份「更新设备心跳时间」的逻辑有两处副本, 改一处忘另一处就会出现行为分叉。 改法:删掉 web 层本地副本(16 行),改为调用 services.tasks._touch_device (两处调用点),并补 import asyncio 以包裹 to_thread。 说明:上一轮报告里提到的「6 组分叉实现」实测需逐组降级——success()/error() 分属不同层(一个是 tuple 返回、一个是 JSONResponse),iter_content 是两个垫片 的适配器,都**不该**合并;只有 _touch_device 是真·逐字重复,故只收敛这一组。 --- web/routers/tasks.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/web/routers/tasks.py b/web/routers/tasks.py index e26b54b..a8beef5 100644 --- a/web/routers/tasks.py +++ b/web/routers/tasks.py @@ -12,6 +12,7 @@ 这些端点读写 core.state 的共享任务表(与任务执行侧同一批对象),因此 看到的是同一份任务状态。 """ +import asyncio import time from typing import Annotated, Any @@ -27,6 +28,7 @@ from core.state import ( REQUEST_STATS, STATS_LOCK, ) +from services import tasks as services_tasks from web import ratelimit from web.deps import SiteUser, require_login from web.request_utils import ( @@ -40,18 +42,6 @@ LoginUser = Annotated[SiteUser, Depends(require_login)] -def _touch_device(device_id: str) -> None: - """记录设备心跳(与 core.state 的 DEVICE_LAST_SEEN 共享)。""" - device_id = str(device_id or '')[:64] - if not device_id: - return - with DEVICE_LAST_SEEN_LOCK: - if len(DEVICE_LAST_SEEN) >= 5000: - for d in sorted(DEVICE_LAST_SEEN, key=lambda k: DEVICE_LAST_SEEN.get(k, 0.0))[:2500]: - DEVICE_LAST_SEEN.pop(d, None) - DEVICE_LAST_SEEN[device_id] = time.time() - - def _owned_by(task: dict[str, Any], user: SiteUser) -> bool: return int(task.get('user_id') or 0) == int(user.id) @@ -183,7 +173,7 @@ async def task_heartbeat(user: LoginUser, request: Request): device_id = str(data.get('device_id') or '').strip()[:64] if not device_id: return error('缺少 device_id 参数') - _touch_device(device_id) + await asyncio.to_thread(services_tasks._touch_device, device_id) resumed = 0 with DOWNLOAD_TASKS_LOCK: for task in DOWNLOAD_TASKS.values(): @@ -209,7 +199,7 @@ async def task_list(user: LoginUser, request: Request): device_id = str(data.get('device_id') or '').strip()[:64] if not device_id: return error('缺少 device_id 参数') - _touch_device(device_id) + await asyncio.to_thread(services_tasks._touch_device, device_id) my_tasks = [] with DOWNLOAD_TASKS_LOCK: for tid, task in DOWNLOAD_TASKS.items():