This commit is contained in:
Ubuntu
2026-08-02 01:27:04 +08:00
parent c20606c003
commit 9379fbb8f8
5 changed files with 6 additions and 79 deletions
+2 -67
View File
@@ -4,13 +4,10 @@
不跑任何算法(无 torch/mediapipe/opencv 依赖)。
"""
import asyncio
import base64
import json
import logging
import time
from contextlib import asynccontextmanager
from io import BytesIO
from pathlib import Path
from typing import Optional
@@ -67,32 +64,15 @@ async def lifespan(app: FastAPI):
else:
app.state._pool_shutdown = None
# 确保标注图目录存在
# 确保标注图目录存在(永久保留,不做定期清理)
static_dir = Path(cfg["static_dir"])
static_dir.mkdir(parents=True, exist_ok=True)
logger.info("标注图目录: %s", static_dir)
# 启动定期清理任务(阶段四)
cleanup_shutdown = asyncio.Event()
cleanup_task = asyncio.create_task(
_cleanup_loop(static_dir, cfg, cleanup_shutdown)
)
app.state._cleanup_shutdown = cleanup_shutdown
app.state._cleanup_task = cleanup_task
logger.info("标注图目录: %s(永久保留,不自动清理)", static_dir)
yield
# 关闭
logger.info("网关关闭中...")
# 停止清理任务
if app.state._cleanup_shutdown:
app.state._cleanup_shutdown.set()
if app.state._cleanup_task:
app.state._cleanup_task.cancel()
try:
await app.state._cleanup_task
except asyncio.CancelledError:
pass
if app.state._pool_shutdown:
await app.state._pool_shutdown()
logger.info("网关已关闭")
@@ -132,51 +112,6 @@ def _get_pool_status_safe():
return {"total": 0, "healthy": 0, "busy": 0}
async def _cleanup_loop(annotations_dir: Path, cfg: dict, shutdown: asyncio.Event):
"""定期清理 static/annotations/ 中过期的标注图文件。
配置项(可选,在 config.json 中设定):
- cleanup.interval_minutes: 清理间隔,默认 60
- cleanup.max_age_hours: 文件保留时长(小时),默认 24
"""
cleanup_cfg = cfg.get("cleanup", {})
interval_s = cleanup_cfg.get("interval_minutes", 60) * 60
max_age_s = cleanup_cfg.get("max_age_hours", 24) * 3600
logger.info(
"清理任务启动 | 间隔=%dmin | 保留=%dh | 目录=%s",
interval_s // 60, max_age_s // 3600, annotations_dir,
)
while not shutdown.is_set():
try:
await asyncio.wait_for(shutdown.wait(), timeout=interval_s)
break # shutdown
except asyncio.TimeoutError:
pass # 正常到时,执行清理
now = time.time()
deleted = 0
for f in annotations_dir.iterdir():
if f.name == ".gitkeep":
continue
if not f.is_file():
continue
try:
age_s = now - f.stat().st_mtime
if age_s > max_age_s:
f.unlink()
deleted += 1
logger.debug("清理过期文件: %s (age=%.1fh)", f.name, age_s / 3600)
except Exception:
logger.warning("清理文件失败: %s", f.name, exc_info=True)
if deleted:
logger.info("清理完成: 删除 %d 个过期文件", deleted)
logger.info("清理任务已停止")
@app.get("/gateway-health", include_in_schema=False)
async def gateway_health():
"""网关自身健康检查(区别于 worker 的 /health)。"""
-4
View File
@@ -22,9 +22,5 @@
"request_timeout_seconds": 600,
"retry_on_failure": true,
"max_retries": 1
},
"cleanup": {
"interval_minutes": 60,
"max_age_hours": 24
}
}
-4
View File
@@ -31,10 +31,6 @@ DEFAULTS = {
"retry_on_failure": True,
"max_retries": 1,
},
"cleanup": {
"interval_minutes": 60,
"max_age_hours": 24,
},
"request_log": {
"enabled": True,
"log_file": "gateway/request_log.jsonl",
+3 -3
View File
@@ -2,8 +2,8 @@
设计原则(与用户约定):
- 入参/出参日志里**绝不内嵌图片 base64**。图片统一存盘后用 URL 引用,保持日志短小。
- 入参图片(image_file / *_base64当前网关不存盘——这里补存到 static_dirin_ 前缀),
复用现有 24h 清理循环自动回收;url 输入图本身就在远端,不重新下载,直接记 URL。
- 入参图片(image_file / *_base64)补存到 static_dirin_ 前缀),永久保留;
url 输入图本身就在远端,不重新下载,直接记 URL。
- 出参响应在 forward.py 已把 base64 改写成 *_url(无大图),记录完整 data,
但用递归摘要器截断超长结构(landmarks、长字符串),单条上限 ~8KB。
@@ -39,7 +39,7 @@ def save_image_bytes(
"""把图片字节存盘并返回公网 URL。失败返回 None(不抛异常)。
存到 static_dir/{prefix}{uuid}.{ext}URL = {public_base_url}/static/annotations/{file}
与 forward.py 的 rewrite_base64_to_url 落盘路径/URL 规则一致,可被同一清理循环回收
与 forward.py 的 rewrite_base64_to_url 落盘路径/URL 规则一致;文件永久保留,不自动清理
"""
if not data:
return None