feat: 请求入口提前创建 pending Usage 记录

在 chat/CLI handler 的流式和非流式请求入口处提前创建 pending 状态的
Usage 记录,让前端可以立即看到"处理中"的请求,提升用户体验。

- 新增 BaseMessageHandler._create_pending_usage() 方法
- ChatHandlerBase 流式/非流式入口调用
- CliMessageHandlerBase 流式/非流式入口调用
- 使用 try-except 包裹,创建失败不影响主流程
This commit is contained in:
fawney19
2026-02-04 03:27:58 +08:00
parent 7f09f191a1
commit f6dac1c38a
3 changed files with 79 additions and 0 deletions

View File

@@ -456,6 +456,45 @@ class BaseMessageHandler:
payload["model"] = mapped_model
return payload
def _create_pending_usage(
self,
model: str,
is_stream: bool,
request_type: str = "chat",
api_format: str | None = None,
request_headers: dict[str, Any] | None = None,
request_body: dict[str, Any] | None = None,
) -> None:
"""在请求开始时创建 pending 状态的 Usage 记录
让前端可以立即看到"处理中"的请求,提升用户体验。
如果创建失败不影响主流程,仅记录警告日志。
Args:
model: 模型名称
is_stream: 是否为流式请求
request_type: 请求类型chat, video 等)
api_format: API 格式
request_headers: 原始请求头
request_body: 原始请求体
"""
try:
UsageService.create_pending_usage(
db=self.db,
request_id=self.request_id,
user=self.user,
api_key=self.api_key,
model=model,
is_stream=is_stream,
request_type=request_type,
api_format=api_format,
request_headers=request_headers,
request_body=request_body,
)
except Exception as exc:
# 创建失败不影响主流程
logger.warning(f"[{self.request_id}] Failed to create pending usage: {exc}")
def _update_usage_to_streaming(self, request_id: str | None = None) -> None:
"""更新 Usage 状态为 streaming流式传输开始时调用

View File

@@ -530,6 +530,16 @@ class ChatHandlerBase(BaseMessageHandler, ABC):
# 转换请求格式
converted_request = await self._convert_request(request)
model = getattr(converted_request, "model", original_request_body.get("model", "unknown"))
# 提前创建 pending 记录,让前端可以立即看到"处理中"
self._create_pending_usage(
model=model,
is_stream=True,
request_type="chat",
api_format=self.FORMAT_ID,
request_headers=original_headers,
request_body=original_request_body,
)
api_format = self.allowed_api_formats[0]
# 可变请求体容器:允许 TaskService 在遇到 Thinking 签名错误时整流请求体后重试
@@ -995,6 +1005,16 @@ class ChatHandlerBase(BaseMessageHandler, ABC):
model = getattr(converted_request, "model", original_request_body.get("model", "unknown"))
api_format = self.allowed_api_formats[0]
# 提前创建 pending 记录,让前端可以立即看到"处理中"
self._create_pending_usage(
model=model,
is_stream=False,
request_type="chat",
api_format=self.FORMAT_ID,
request_headers=original_headers,
request_body=original_request_body,
)
# 可变请求体容器:允许 TaskService 在遇到 Thinking 签名错误时整流请求体后重试
# 结构: {"body": 实际请求体, "_rectified": 是否已整流, "_rectified_this_turn": 本轮是否整流}
request_body_ref: dict[str, Any] = {"body": original_request_body}

View File

@@ -537,6 +537,16 @@ class CliMessageHandlerBase(BaseMessageHandler):
# 注意:使用 original_request_body因为整流只修改 messages不影响 model 字段
model = self.extract_model_from_request(original_request_body, path_params)
# 提前创建 pending 记录,让前端可以立即看到"处理中"
self._create_pending_usage(
model=model,
is_stream=True,
request_type="chat",
api_format=self.FORMAT_ID,
request_headers=original_headers,
request_body=original_request_body,
)
# 创建流上下文
ctx = StreamContext(
model=model,
@@ -2209,6 +2219,16 @@ class CliMessageHandlerBase(BaseMessageHandler):
api_format = self.allowed_api_formats[0]
sync_start_time = time.time()
# 提前创建 pending 记录,让前端可以立即看到"处理中"
self._create_pending_usage(
model=model,
is_stream=False,
request_type="chat",
api_format=self.FORMAT_ID,
request_headers=original_headers,
request_body=original_request_body,
)
provider_name = None
response_json = None
status_code = 200