mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
feat: 优化用量状态同步机制和 OpenAI CLI 流式转换
- 增加状态回退保护,防止异步响应覆盖已知状态 - 添加轮询并发保护 (pollInFlight),避免重复请求 - 支持 cancelled 状态筛选和显示 - 前端 mergeRecordStatus 保护活跃记录状态 - 后端 streaming 状态同步更新改为使用当前 DB 会话 - OpenAI CLI 流式转换增加工具调用事件支持 - 轮询接口新增 target_model 字段返回 - 修复迁移脚本 inspector 缓存问题,改用 information_schema
This commit is contained in:
@@ -2676,7 +2676,28 @@ class CliMessageHandlerBase(BaseMessageHandler):
|
||||
ctx.record_first_byte_time(self.start_time)
|
||||
state["first_yield"] = False
|
||||
if not state["streaming_updated"]:
|
||||
self._update_usage_to_streaming_with_ctx(ctx)
|
||||
# 优先使用当前请求的 DB 会话同步更新,避免状态延迟或丢失
|
||||
try:
|
||||
from src.services.usage import UsageService
|
||||
|
||||
UsageService.update_usage_status(
|
||||
db=self.db,
|
||||
request_id=self.request_id,
|
||||
status="streaming",
|
||||
provider=ctx.provider_name,
|
||||
target_model=ctx.mapped_model,
|
||||
provider_id=ctx.provider_id,
|
||||
provider_endpoint_id=ctx.endpoint_id,
|
||||
provider_api_key_id=ctx.key_id,
|
||||
first_byte_time_ms=ctx.first_byte_time_ms,
|
||||
api_format=ctx.api_format,
|
||||
endpoint_api_format=ctx.provider_api_format or None,
|
||||
has_format_conversion=ctx.needs_conversion,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"[{self.request_id}] 同步更新 streaming 状态失败: {e}")
|
||||
# 回退到后台任务更新
|
||||
self._update_usage_to_streaming_with_ctx(ctx)
|
||||
state["streaming_updated"] = True
|
||||
|
||||
def _convert_sse_line(
|
||||
|
||||
@@ -112,6 +112,7 @@ class StreamTelemetryRecorder:
|
||||
|
||||
try:
|
||||
await self._dispatch_record(
|
||||
bg_db,
|
||||
writer,
|
||||
ctx,
|
||||
original_headers,
|
||||
@@ -137,6 +138,7 @@ class StreamTelemetryRecorder:
|
||||
if response_body is None and should_log_body:
|
||||
response_body = ctx.build_response_body(response_time_ms)
|
||||
await self._dispatch_record(
|
||||
bg_db,
|
||||
db_writer,
|
||||
ctx,
|
||||
original_headers,
|
||||
@@ -438,6 +440,7 @@ class StreamTelemetryRecorder:
|
||||
|
||||
async def _dispatch_record(
|
||||
self,
|
||||
db: Session,
|
||||
writer: TelemetryWriter,
|
||||
ctx: StreamContext,
|
||||
original_headers: dict[str, str],
|
||||
@@ -455,6 +458,14 @@ class StreamTelemetryRecorder:
|
||||
response_body,
|
||||
response_time_ms,
|
||||
)
|
||||
# Queue writer 异步落库可能造成 UI 延迟,先直接更新 Usage 状态
|
||||
if isinstance(writer, QueueTelemetryWriter):
|
||||
await self._update_usage_status_directly(
|
||||
db=db,
|
||||
status=self._get_status_from_ctx(ctx),
|
||||
response_time_ms=response_time_ms,
|
||||
status_code=ctx.status_code,
|
||||
)
|
||||
elif ctx.is_client_disconnected():
|
||||
await self._record_cancelled(
|
||||
writer,
|
||||
@@ -464,6 +475,14 @@ class StreamTelemetryRecorder:
|
||||
response_body,
|
||||
response_time_ms,
|
||||
)
|
||||
# Queue writer 异步落库可能造成 UI 延迟,先直接更新 Usage 状态
|
||||
if isinstance(writer, QueueTelemetryWriter):
|
||||
await self._update_usage_status_directly(
|
||||
db=db,
|
||||
status="cancelled",
|
||||
response_time_ms=response_time_ms,
|
||||
status_code=ctx.status_code,
|
||||
)
|
||||
else:
|
||||
await self._record_failure(
|
||||
writer,
|
||||
@@ -473,6 +492,15 @@ class StreamTelemetryRecorder:
|
||||
response_body,
|
||||
response_time_ms,
|
||||
)
|
||||
# Queue writer 异步落库可能造成 UI 延迟,先直接更新 Usage 状态
|
||||
if isinstance(writer, QueueTelemetryWriter):
|
||||
await self._update_usage_status_directly(
|
||||
db=db,
|
||||
status=self._get_status_from_ctx(ctx),
|
||||
response_time_ms=response_time_ms,
|
||||
status_code=ctx.status_code,
|
||||
error_message=ctx.error_message or f"HTTP {ctx.status_code}",
|
||||
)
|
||||
|
||||
def _get_status_from_ctx(self, ctx: StreamContext) -> str:
|
||||
"""根据上下文获取状态字符串"""
|
||||
|
||||
Reference in New Issue
Block a user