a3216 commited on
Commit
185252d
·
verified ·
1 Parent(s): 5b716a5

sync from GitHub da1963f: feat: 增加超时保护和错误处理,优化用户文件的获取和下载逻辑 fix: 更新版本号至183,调整用户文件同步间隔至1分钟 fix: 扩展请求日志中记录的路径

Browse files
app/api/user_files.py CHANGED
@@ -299,10 +299,18 @@ async def list_my_files(user: dict = Depends(require_user)):
299
  user_id = str(user["sub"])
300
  items = _list_files_from_db(user_id)
301
  # SQLite 为空时尝试从 Hub 恢复(Space 重建场景)
302
- if not items:
303
- restored = await _restore_files_from_hub_async(user_id)
304
- if restored > 0:
305
- items = _list_files_from_db(user_id)
 
 
 
 
 
 
 
 
306
  return ok_with_cors({"items": items, "count": len(items)})
307
 
308
 
@@ -397,36 +405,50 @@ async def download_file(
397
  (key,),
398
  ).fetchone()
399
  # SQLite 没有则尝试从 Hub 恢复单条 meta(Space 重建场景)
400
- if not row:
401
- metas = await user_files_store.restore_file_metas(user_id)
402
- target = next((m for m in metas if m.get("key") == key), None)
403
- if target:
404
- try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  with get_conn() as conn:
406
- conn.execute(
407
- "INSERT OR IGNORE INTO file_meta(key, namespace, filename, mime, size, "
408
- "sha256, uploaded_at, uploaded_by, access_key, refs) "
409
- "VALUES(?,?,?,?,?,?,?,?,?,?)",
410
- (target["key"], NS_USER_FILES, target.get("filename", "unnamed"),
411
- target.get("mime", "application/octet-stream"),
412
- int(target.get("size", 0)), target.get("sha256"),
413
- int(target.get("uploaded_at", 0)), str(user_id),
414
- target.get("access_key", ""), ""),
415
- )
416
- except Exception:
417
- pass
418
- with get_conn() as conn:
419
- row = conn.execute(
420
- "SELECT filename, mime, uploaded_by FROM file_meta WHERE key = ?",
421
- (key,),
422
- ).fetchone()
423
  if not row:
424
  raise HttpError("file not found", status=404, code="not_found")
425
  if row["uploaded_by"] != user_id:
426
  raise HttpError("forbidden", status=403, code="forbidden")
427
 
428
- # 读文件内容:本地优先,Hub 回退
429
- content = user_files_store.download_user_file_content(user_id, key)
 
 
 
 
 
 
 
430
  if content is None:
431
  raise HttpError("file content missing", status=410, code="gone")
432
 
 
299
  user_id = str(user["sub"])
300
  items = _list_files_from_db(user_id)
301
  # SQLite 为空时尝试从 Hub 恢复(Space 重建场景)
302
+ # 加超时保护,避免 Hub 网络问题导致前端一直卡在"拉取列表"
303
+ if not items and is_hub_enabled():
304
+ try:
305
+ restored = await asyncio.wait_for(
306
+ _restore_files_from_hub_async(user_id), timeout=8.0
307
+ )
308
+ if restored > 0:
309
+ items = _list_files_from_db(user_id)
310
+ except asyncio.TimeoutError:
311
+ logger.warning("[list] restore from hub timeout uid=%s, return empty", user_id)
312
+ except Exception as e:
313
+ logger.warning("[list] restore from hub failed uid=%s: %s", user_id, e)
314
  return ok_with_cors({"items": items, "count": len(items)})
315
 
316
 
 
405
  (key,),
406
  ).fetchone()
407
  # SQLite 没有则尝试从 Hub 恢复单条 meta(Space 重建场景)
408
+ if not row and is_hub_enabled():
409
+ try:
410
+ metas = await asyncio.wait_for(
411
+ user_files_store.restore_file_metas(user_id), timeout=8.0
412
+ )
413
+ target = next((m for m in metas if m.get("key") == key), None)
414
+ if target:
415
+ try:
416
+ with get_conn() as conn:
417
+ conn.execute(
418
+ "INSERT OR IGNORE INTO file_meta(key, namespace, filename, mime, size, "
419
+ "sha256, uploaded_at, uploaded_by, access_key, refs) "
420
+ "VALUES(?,?,?,?,?,?,?,?,?,?)",
421
+ (target["key"], NS_USER_FILES, target.get("filename", "unnamed"),
422
+ target.get("mime", "application/octet-stream"),
423
+ int(target.get("size", 0)), target.get("sha256"),
424
+ int(target.get("uploaded_at", 0)), str(user_id),
425
+ target.get("access_key", ""), ""),
426
+ )
427
+ except Exception:
428
+ pass
429
  with get_conn() as conn:
430
+ row = conn.execute(
431
+ "SELECT filename, mime, uploaded_by FROM file_meta WHERE key = ?",
432
+ (key,),
433
+ ).fetchone()
434
+ except asyncio.TimeoutError:
435
+ logger.warning("[download] restore meta timeout uid=%s key=%s", user_id, key)
436
+ except Exception as e:
437
+ logger.warning("[download] restore meta failed uid=%s key=%s: %s", user_id, key, e)
 
 
 
 
 
 
 
 
 
438
  if not row:
439
  raise HttpError("file not found", status=404, code="not_found")
440
  if row["uploaded_by"] != user_id:
441
  raise HttpError("forbidden", status=403, code="forbidden")
442
 
443
+ # 读文件内容:本地优先,Hub 回退(同步网络 IO 放到线程池,加超时保护)
444
+ try:
445
+ content = await asyncio.wait_for(
446
+ asyncio.to_thread(user_files_store.download_user_file_content, user_id, key),
447
+ timeout=15.0,
448
+ )
449
+ except asyncio.TimeoutError:
450
+ logger.warning("[download] content fetch timeout uid=%s key=%s", user_id, key)
451
+ raise HttpError("file content fetch timeout", status=504, code="upstream_timeout")
452
  if content is None:
453
  raise HttpError("file content missing", status=410, code="gone")
454
 
app/request_log_middleware.py CHANGED
@@ -25,7 +25,7 @@ from .services import request_log_store
25
 
26
 
27
  # 记录范围
28
- _RECORDED_PREFIXES = ("/v1/", "/admin/api/")
29
  # 排除项(避免日志刷屏:admin HTML 轮询、health)
30
  _EXCLUDED_PATHS = {"/admin/api/request-log"} # 避免查询日志本身被记录导致递归刷屏
31
 
 
25
 
26
 
27
  # 记录范围
28
+ _RECORDED_PREFIXES = ("/v1/", "/admin/api/", "/u/api/")
29
  # 排除项(避免日志刷屏:admin HTML 轮询、health)
30
  _EXCLUDED_PATHS = {"/admin/api/request-log"} # 避免查询日志本身被记录导致递归刷屏
31
 
app/services/user_files_sync.py CHANGED
@@ -23,7 +23,7 @@ from ..hf_storage import (
23
  logger = logging.getLogger(__name__)
24
 
25
  # 同步间隔(秒)
26
- SYNC_INTERVAL_SEC = 300 # 5 分钟
27
 
28
  # 需要定时扫描同步的 namespace 前缀
29
  SYNC_NS_PREFIXES = ["user_accounts", "user_files/", "user_files_meta/"]
 
23
  logger = logging.getLogger(__name__)
24
 
25
  # 同步间隔(秒)
26
+ SYNC_INTERVAL_SEC = 60 # 1 分钟
27
 
28
  # 需要定时扫描同步的 namespace 前缀
29
  SYNC_NS_PREFIXES = ["user_accounts", "user_files/", "user_files_meta/"]