系统定时任务日志持久化:新增入库与后台查询
- 新增系统任务日志表 t_system_job_logs,持久化记录每次执行结果、摘要、耗时、详情JSON\n- SystemJobLoader 注册任务时增加执行包装器:成功/失败均写入数据库日志,失败后继续抛出保证运行态状态一致\n- 系统任务后台日志接口改为查询数据库日志(不再依赖仅内存的 async_job logs),解决重启后日志丢失问题\n- 保持前端日志字段兼容,接口返回映射为 time/level/message 结构
This commit is contained in:
@@ -15,7 +15,7 @@ class SystemJobDBOperator(BaseDBOperator):
|
||||
super().__init__(db_manager)
|
||||
|
||||
def init_tables(self) -> bool:
|
||||
"""初始化系统任务配置表。"""
|
||||
"""初始化系统任务配置表与日志表。"""
|
||||
try:
|
||||
self.execute_update(
|
||||
"""
|
||||
@@ -31,6 +31,21 @@ class SystemJobDBOperator(BaseDBOperator):
|
||||
)
|
||||
"""
|
||||
)
|
||||
# 系统任务执行日志表:用于持久化记录每次任务执行结果,避免重启后日志丢失。
|
||||
self.execute_update(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS t_system_job_logs (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
job_key VARCHAR(64) NOT NULL,
|
||||
triggered_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
summary VARCHAR(255) DEFAULT '',
|
||||
detail_json JSON DEFAULT NULL,
|
||||
duration_ms INT DEFAULT NULL,
|
||||
INDEX idx_job_time (job_key, triggered_at)
|
||||
)
|
||||
"""
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"初始化 t_system_jobs 失败: {e}")
|
||||
@@ -110,3 +125,47 @@ class SystemJobDBOperator(BaseDBOperator):
|
||||
|
||||
def delete_job(self, job_key: str) -> bool:
|
||||
return self.execute_update("DELETE FROM t_system_jobs WHERE job_key = %s", (job_key,))
|
||||
|
||||
def create_job_log(
|
||||
self,
|
||||
job_key: str,
|
||||
status: str,
|
||||
summary: str,
|
||||
detail: Optional[Dict[str, Any]] = None,
|
||||
duration_ms: Optional[int] = None,
|
||||
) -> bool:
|
||||
"""写入系统任务执行日志。"""
|
||||
sql = """
|
||||
INSERT INTO t_system_job_logs (job_key, status, summary, detail_json, duration_ms)
|
||||
VALUES (%s, %s, %s, %s, %s)
|
||||
"""
|
||||
params = (
|
||||
str(job_key),
|
||||
str(status),
|
||||
str(summary or ""),
|
||||
json.dumps(detail or {}, ensure_ascii=False),
|
||||
duration_ms if duration_ms is not None else None,
|
||||
)
|
||||
return self.execute_update(sql, params)
|
||||
|
||||
def get_job_logs(self, job_key: str, limit: int = 100) -> List[Dict[str, Any]]:
|
||||
"""获取系统任务持久化日志。"""
|
||||
rows = self.execute_query(
|
||||
"""
|
||||
SELECT * FROM t_system_job_logs
|
||||
WHERE job_key = %s
|
||||
ORDER BY triggered_at DESC
|
||||
LIMIT %s
|
||||
""",
|
||||
(str(job_key), int(limit)),
|
||||
) or []
|
||||
for row in rows:
|
||||
detail = row.get("detail_json")
|
||||
if isinstance(detail, str):
|
||||
try:
|
||||
row["detail_json"] = json.loads(detail)
|
||||
except json.JSONDecodeError:
|
||||
row["detail_json"] = {}
|
||||
elif detail is None:
|
||||
row["detail_json"] = {}
|
||||
return rows
|
||||
|
||||
Reference in New Issue
Block a user