修复: pull 端点 aria2 子进程走 asyncio.to_thread (async端点同步阻塞卡死事件循环, pull-status 轮询超时导致进度条0%)
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user