fix(alembic,pipeline,resilience): 数据库迁移与异常处理健壮性修复

- alembic env: 改用事务级 advisory lock (pg_advisory_xact_lock),事务结束自动释放
- 迁移脚本: 使用原生 SQL IF NOT EXISTS/IF EXISTS 替代运行时列检查
- pipeline: SQLAlchemy 异常后先回滚事务再写审计,防止 aborted 状态二次报错
- resilience: ProgrammingError 标记为不可恢复,缩减 DB 重试异常范围
- 前端: 端点规则支持拖拽排序
This commit is contained in:
fawney19
2026-03-02 18:02:21 +08:00
parent 5f1c74aca0
commit 3384c6d666
5 changed files with 218 additions and 49 deletions

View File

@@ -5,6 +5,7 @@ from enum import Enum
from typing import TYPE_CHECKING, Any
from fastapi import HTTPException, Request
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session
from src.config.settings import config
@@ -199,6 +200,12 @@ class ApiRequestPipeline:
except Exception as exc:
handle_duration = PerfRecorder.stop(handle_start, "pipeline_handle", labels=perf_labels)
_record_perf_metric("handle_ms", handle_duration)
if isinstance(exc, SQLAlchemyError):
# SQL 执行失败后事务会进入 aborted 状态;先回滚,避免审计写入二次报错。
try:
context.db.rollback()
except Exception as rollback_exc:
logger.debug(f"[Pipeline] 回滚失败(可忽略): {rollback_exc}")
self._record_audit_event(
context,
adapter,

View File

@@ -128,19 +128,27 @@ class ResilienceManager:
# 数据库连接错误 - 只捕获特定的数据库相关异常
try:
from sqlalchemy.exc import (
DatabaseError,
DisconnectionError,
OperationalError,
StatementError,
ProgrammingError,
)
from sqlalchemy.exc import TimeoutError as SQLTimeoutError
# SQL/Schema 编程错误(如缺列/缺表)不应误判为“连接异常重试”。
self.add_error_pattern(
ErrorPattern(
error_types=[ProgrammingError],
severity=ErrorSeverity.HIGH,
recovery_strategy=RecoveryStrategy.USER_NOTIFY,
user_message="数据库结构与当前版本不兼容,请执行 alembic upgrade head 后重试",
auto_recover=False,
)
)
db_exceptions = [
OperationalError,
DisconnectionError,
SQLTimeoutError,
StatementError,
DatabaseError,
]
except ImportError:
# 如果SQLAlchemy不可用使用通用异常类型