v2.8.0 清空历史真正物理删除 + 请求超时可配修复慢接口被掐断

1. 清空历史=真正清空(不再只是删行留痕):
   - 清空前先停止所有运行中测试线程,避免其继续写入孤儿数据
   - DELETE 后重置自增序列(sqlite_sequence),新测试 ID 从 1 开始
   - WAL checkpoint(TRUNCATE) + VACUUM 物理回收文件空间,数据不可恢复
   - 单条删除删光时同样重置自增序列

2. 慢接口被掐断修复(预处理/首字耗时过长 Read timed out):
   - 读取超时默认 300s→1800s(30分钟),连接 60s
   - 「速度测试配置」新增 请求超时(秒) 输入框(默认1800),测试连接+速度采样共用,按次可调(如3600)
   - 超时错误改为友好提示:等待响应超时(超过N秒未收到数据),引导调大请求超时,不再裸抛 Read timed out
   - 测试启动日志打印当前超时配置
   - 修复案例: 18008 Qwen3.8-FP8 131072 长上下文预填充被 300s 掐断
This commit is contained in:
2026-09-13 12:38:40 +08:00
parent 31e5bbb873
commit ccfd7eb689
7 changed files with 94 additions and 12 deletions
+21 -3
View File
@@ -3,6 +3,7 @@
import io
import json
import subprocess
import time
from datetime import datetime
import requests
@@ -112,13 +113,17 @@ def list_models_api():
@app.route("/api/configs/test", methods=["POST"])
def test_config():
cfg = _fill_defaults(request.get_json(force=True) or {})
body = request.get_json(force=True) or {}
cfg = _fill_defaults(body)
if not cfg.get("api_key"):
return jsonify({"ok": False, "error": "请填写 API Key"}), 400
try:
# 连接测试:只要流式请求成功返回(哪怕正文为空/只有思维链)都算连通
# 慢接口长预处理可能长时间等不到首字,这里直接用请求里带的超时(默认 30 分钟),避免误判接口不通
m = call_stream(cfg, "你好,请简要回答:1+1=",
{"max_tokens": 32, "avoid_cache": False})
{"max_tokens": 32, "avoid_cache": False,
"read_timeout": body.get("read_timeout"),
"connect_timeout": body.get("connect_timeout")})
note = ""
if not (m.get("output_tokens") or m.get("output_chars")):
note = "(连接正常,但本次未返回正文内容,可能为推理型模型)"
@@ -188,7 +193,20 @@ def list_tests():
@app.route("/api/tests", methods=["DELETE"])
def clear_tests():
"""一键清空全部测试历史(含采样指标与日志)"""
"""一键清空全部测试历史(含采样指标与日志)
先停止所有运行中的测试线程,避免清空后它们继续写入孤儿数据;
再由 db.clear_tests 做物理删除(重置自增 + VACUUM 瘦身),真正清空、不可恢复。"""
# 1) 停止所有运行中的测试,并等待其退出
alive = [r for r in RUNNERS.values() if r.is_alive()]
for r in alive:
r.request_cancel()
if alive:
deadline = time.time() + 5
for r in alive:
if r.is_alive():
r.join(timeout=max(0.1, deadline - time.time()))
RUNNERS.clear()
# 2) 物理清空数据库
db.clear_tests()
return jsonify({"ok": True})