36 lines
1.5 KiB
Python
36 lines
1.5 KiB
Python
|
|
"""只按明确的源驱动错误分类,不把含凭据的驱动文本写入响应。"""
|
|||
|
|
|
|||
|
|
from sqlalchemy.exc import TimeoutError as PoolTimeoutError
|
|||
|
|
|
|||
|
|
TRANSIENT_CODES = frozenset({"SOURCE_CONNECTION_LOST", "SOURCE_TIMEOUT"})
|
|||
|
|
MESSAGES = {
|
|||
|
|
"SOURCE_CONNECTION_LOST": "源连接中断,请检查网络和只读连接",
|
|||
|
|
"SOURCE_TIMEOUT": "源连接或查询超时",
|
|||
|
|
"SOURCE_AUTH_ERROR": "源账号认证失败,请核对只读账号配置",
|
|||
|
|
"SOURCE_SCHEMA_ERROR": "源表或字段不匹配,请核对版本与映射",
|
|||
|
|
"SOURCE_CONFIG_ERROR": "源连接配置不完整或任务排队后发生变化",
|
|||
|
|
"SOURCE_DRIVER_ERROR": "源数据库驱动不可用,请检查已验证的ODBC驱动",
|
|||
|
|
"QUERY_FILE_MISSING": "缺少源查询文件,请核对部署包",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
def classify_source_error(exc, fallback="READ_ERROR"):
|
|||
|
|
if isinstance(exc, (TimeoutError, PoolTimeoutError)):
|
|||
|
|
return "SOURCE_TIMEOUT"
|
|||
|
|
if isinstance(exc, ModuleNotFoundError):
|
|||
|
|
return "SOURCE_DRIVER_ERROR"
|
|||
|
|
if isinstance(exc, FileNotFoundError):
|
|||
|
|
return "QUERY_FILE_MISSING"
|
|||
|
|
original = getattr(exc, "orig", exc)
|
|||
|
|
args = getattr(original, "args", ())
|
|||
|
|
state = str(args[0]).upper() if args else ""
|
|||
|
|
if state in {"HYT00", "HYT01"}:
|
|||
|
|
return "SOURCE_TIMEOUT"
|
|||
|
|
if state in {"08S01", "08001", "08003", "08006"}:
|
|||
|
|
return "SOURCE_CONNECTION_LOST"
|
|||
|
|
if state == "28000":
|
|||
|
|
return "SOURCE_AUTH_ERROR"
|
|||
|
|
if state in {"42S02", "42S22", "07002"}:
|
|||
|
|
return "SOURCE_SCHEMA_ERROR"
|
|||
|
|
return fallback
|