73 lines
2.4 KiB
Python
73 lines
2.4 KiB
Python
"""NL2SQL 运维任务执行历史适配器。"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import text
|
|
|
|
from nl2sql.audit import _sanitize
|
|
|
|
|
|
async def record_job_history(db, result, *, elapsed_ms: float, parameter_summary: dict | None = None) -> None:
|
|
"""保存任务结果摘要,不保存原始参数和连接凭据。"""
|
|
statement = text(
|
|
"""
|
|
INSERT INTO nl2sql_job_history
|
|
(job_name, status, attempts, detail, error_type, parameter_summary, elapsed_ms, create_time)
|
|
VALUES
|
|
(:job_name, :status, :attempts, :detail, :error_type, :parameter_summary, :elapsed_ms, :create_time)
|
|
"""
|
|
)
|
|
await db.execute(
|
|
statement,
|
|
{
|
|
"job_name": result.name,
|
|
"status": result.status,
|
|
"attempts": result.attempts,
|
|
"detail": json.dumps(_sanitize(result.detail or {}), ensure_ascii=False),
|
|
"error_type": result.error_type,
|
|
"parameter_summary": json.dumps(_sanitize(parameter_summary or {}), ensure_ascii=False),
|
|
"elapsed_ms": elapsed_ms,
|
|
"create_time": datetime.now(),
|
|
},
|
|
)
|
|
await db.commit()
|
|
|
|
|
|
async def record_job_history_safely(db, result, *, elapsed_ms: float, parameter_summary: dict | None = None) -> bool:
|
|
"""任务历史写入失败时降级,不影响任务结果返回。"""
|
|
try:
|
|
await record_job_history(
|
|
db,
|
|
result,
|
|
elapsed_ms=elapsed_ms,
|
|
parameter_summary=parameter_summary,
|
|
)
|
|
except Exception: # noqa: BLE001 历史故障不能阻断运维任务
|
|
return False
|
|
return True
|
|
|
|
|
|
async def list_job_history(db, *, page: int = 1, page_size: int = 20, status: str | None = None) -> list[dict]:
|
|
"""分页查询任务历史,只返回执行摘要,不返回 detail 明细。"""
|
|
conditions = "WHERE (:status IS NULL OR status = :status)"
|
|
statement = text(
|
|
f"""
|
|
SELECT id, job_name, status, attempts, error_type, elapsed_ms, create_time
|
|
FROM nl2sql_job_history
|
|
{conditions}
|
|
ORDER BY id DESC
|
|
LIMIT :limit OFFSET :offset
|
|
"""
|
|
)
|
|
result = await db.execute(
|
|
statement,
|
|
{
|
|
"status": status,
|
|
"limit": max(1, min(page_size, 100)),
|
|
"offset": max(0, (page - 1) * page_size),
|
|
},
|
|
)
|
|
return [dict(row) for row in result.mappings().all()]
|