api: complete 幂等 (已完成直接返回 file_id, 客户端超时重试不重复入库); db: get_file_by_transfer

This commit is contained in:
lou
2026-08-10 01:00:23 +08:00
parent cf1f143a0c
commit eba9d36450
3 changed files with 20 additions and 0 deletions
+4
View File
@@ -103,6 +103,10 @@ async def put_chunk(transfer_id: str, idx: int, request: Request):
async def complete(transfer_id: str):
if tasks.get(transfer_id) is None:
return JSONResponse(status_code=404, content={"error": "任务不存在"})
# 幂等: 已完成的任务直接返回已有 file_id (客户端超时重试/断线重连场景)
done_rec = db.get_file_by_transfer(transfer_id)
if done_rec is not None:
return {"status": "done", "file_id": done_rec["file_id"]}
try:
tasks.set_status(transfer_id, "assembling")
merged = assembler.assemble(transfer_id)
+9
View File
@@ -177,6 +177,15 @@ class ServerDB:
)
return file_id
def get_file_by_transfer(self, transfer_id: str) -> dict[str, Any] | None:
"""按任务查已入库文件 (complete 幂等: 已完成直接返回)"""
with self._conn() as conn:
row = conn.execute(
"SELECT file_id, file_name, path, size FROM files WHERE transfer_id = ?",
(transfer_id,),
).fetchone()
return dict(row) if row else None
def list_files(self) -> list[dict[str, Any]]:
"""全部文件记录 (ls 端点)"""
with self._conn() as conn:
+7
View File
@@ -175,6 +175,13 @@ class ServerPipelineTest(unittest.TestCase):
# 未知 file_id -> 404
self.assertEqual(self.client.get("/api/files/nope").status_code, 404)
# complete 幂等: 重复 complete 返回同一个 file_id, 不新增入库记录
before = len(self.client.get("/api/files").json()["files"])
r = self.client.post(f"/api/transfer/{tid}/complete")
self.assertEqual(r.status_code, 200)
self.assertEqual(r.json()["file_id"], file_id)
self.assertEqual(len(self.client.get("/api/files").json()["files"]), before)
if __name__ == "__main__":
unittest.main()