修复: pull 端点 aria2 子进程走 asyncio.to_thread (async端点同步阻塞卡死事件循环, pull-status 轮询超时导致进度条0%)

This commit is contained in:
lou
2026-08-10 21:00:42 +08:00
parent 1beb1fbb82
commit 1491b3b4bc
+20 -1
View File
@@ -15,6 +15,7 @@ API 层 (api)
全部端点需 Authorization: Bearer <token> (与客户端预共享)
"""
import asyncio
import base64
import json
import logging
@@ -245,6 +246,8 @@ async def pull_chunks(transfer_id: str, request: Request, username: str = Depend
body: {base_url, token} —— 客户端临时服务地址 + 一次性拉取令牌
卷文件拉取后逐卷走 receiver.receive 校验 (大小+SHA-256) 落盘。
aria2 子进程走 asyncio.to_thread: 同步阻塞会卡死事件循环,
导致 pull-status/其他请求全部排队超时 (进度条 0%)。
"""
task = tasks.get(transfer_id)
if task is None:
@@ -266,7 +269,8 @@ async def pull_chunks(transfer_id: str, request: Request, username: str = Depend
for idx in range(1, chunk_count + 1):
f.write(f"{base_url}/pull/{transfer_id}/{idx}?token={pull_token}\n")
try:
r = subprocess.run(
r = await asyncio.to_thread(
subprocess.run,
[aria2, "-i", str(urls_file), "-d", str(chunk_dir),
"--max-concurrent-downloads=8", "--split=4", "--max-connection-per-server=4",
"--min-split-size=1M", "--file-allocation=none", "--allow-overwrite=true",
@@ -299,6 +303,21 @@ async def pull_chunks(transfer_id: str, request: Request, username: str = Depend
return {"ok": True, "pulled": pulled, "total": chunk_count}
@app.get("/api/transfer/{transfer_id}/pull-status")
async def pull_status(transfer_id: str, request: Request, username: str = Depends(verify_token)):
"""aria2 拉取进度: 已落盘卷文件数 (aria2 每拉完一卷落盘, received 标记在全部拉完后才打)"""
task = tasks.get(transfer_id)
if task is None:
return JSONResponse(status_code=404, content={"error": "任务不存在"})
chunk_dir = TMP_ROOT / transfer_id
n = 0
if chunk_dir.is_dir():
for p in chunk_dir.iterdir():
if p.name != "urls.txt" and p.suffix not in (".aria2", ".tmp") and p.name.isdigit():
n += 1
return {"pulled": n, "total": task.get("chunk_count", 0)}
@app.post("/api/transfer/{transfer_id}/complete")
async def complete(transfer_id: str, request: Request, username: str = Depends(verify_token)):
if tasks.get(transfer_id) is None: