Restore AI workflow design nodes

This commit is contained in:
2026-06-09 21:18:33 +08:00
parent fbd726ebdf
commit cb45c0a068
71 changed files with 22676 additions and 21 deletions
@@ -0,0 +1,308 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
表单数据操作 — 细粒度异常体系
异常层次:
FormDataException (所有表单数据异常的基类)
├── FormNotFoundException (表单不存在)
├── RecordNotFoundException (记录不存在)
├── FormDataValidationError (数据校验失败的基类)
│ ├── UniqueConstraintError (唯一约束冲突)
│ ├── NotNullConstraintError (非空约束违反)
│ ├── CheckConstraintError (CHECK 约束违反)
│ ├── ForeignKeyConstraintError (外键约束违反)
│ ├── DataTypeMismatchError (数据类型不匹配)
│ └── DataTooLongError (数据超长)
├── FormDataSchemaError (表结构/配置错误的基类)
│ ├── TableNotFoundError (表不存在)
│ └── ColumnNotFoundError (列不存在)
├── FormDataConnectionError (连接相关错误的基类)
│ ├── DatabaseConnectionError (连接失败/断开)
│ ├── ConnectionPoolExhaustedError (连接池耗尽)
│ └── ConnectionTimeoutError (连接超时)
├── FormDataConcurrencyError (并发相关错误的基类)
│ ├── DeadlockError (死锁)
│ └── LockTimeoutError (锁等待超时)
├── QueryError (SQL 查询构建/执行错误)
└── InternalDatabaseError (其他数据库内部错误)
每个异常类携带 error_code 和结构化的上下文信息 (context),
方便 API 层映射到 HTTP 响应 + 前端根据 error_code 做差异化处理。
"""
from __future__ import annotations
from typing import Any, Dict, Optional
# =====================================================================
# 基类
# =====================================================================
class FormDataException(Exception):
"""表单数据操作异常基类"""
error_code: str = "FORM_DATA_ERROR"
http_status: int = 400
def __init__(
self,
message: str,
*,
error_code: Optional[str] = None,
http_status: Optional[int] = None,
context: Optional[Dict[str, Any]] = None,
):
super().__init__(message)
if error_code is not None:
self.error_code = error_code
if http_status is not None:
self.http_status = http_status
self.context: Dict[str, Any] = context or {}
# =====================================================================
# 资源不存在
# =====================================================================
class FormNotFoundException(FormDataException):
"""表单定义不存在"""
error_code = "FORM_NOT_FOUND"
http_status = 404
def __init__(self, form_code: str):
super().__init__(
f"表单不存在: {form_code}",
context={"form_code": form_code},
)
class RecordNotFoundException(FormDataException):
"""记录不存在"""
error_code = "RECORD_NOT_FOUND"
http_status = 404
def __init__(self, pk: Any, *, table: str = ""):
super().__init__(
f"数据不存在: {pk}",
context={"pk": str(pk), "table": table},
)
# =====================================================================
# 数据校验 / 约束违反
# =====================================================================
class FormDataValidationError(FormDataException):
"""数据校验失败的基类"""
error_code = "VALIDATION_ERROR"
http_status = 400
class UniqueConstraintError(FormDataValidationError):
"""唯一约束冲突(含重复数据信息)"""
error_code = "UNIQUE_CONSTRAINT_VIOLATION"
def __init__(
self,
message: str = "数据重复,违反唯一约束",
*,
fields: Optional[list[str]] = None,
constraint_name: str = "",
):
super().__init__(
message,
context={"fields": fields or [], "constraint_name": constraint_name},
)
class NotNullConstraintError(FormDataValidationError):
"""非空约束违反"""
error_code = "NOT_NULL_VIOLATION"
def __init__(self, column: str = ""):
msg = f"字段 '{column}' 不能为空" if column else "存在必填字段为空"
super().__init__(msg, context={"column": column})
class CheckConstraintError(FormDataValidationError):
"""CHECK 约束违反"""
error_code = "CHECK_CONSTRAINT_VIOLATION"
def __init__(self, constraint_name: str = "", detail: str = ""):
msg = "数据不满足校验规则"
if constraint_name:
msg += f" ({constraint_name})"
super().__init__(msg, context={"constraint_name": constraint_name, "detail": detail})
class ForeignKeyConstraintError(FormDataValidationError):
"""外键约束违反(删除/更新时关联数据存在)"""
error_code = "FOREIGN_KEY_VIOLATION"
def __init__(
self,
message: str = "",
*,
detail: str = "",
referenced_table: str = "",
constraint_name: str = "",
):
if not message:
message = "操作失败,该数据被其他数据引用"
if referenced_table:
message = (
f"无法删除,该数据已被「{referenced_table}」引用,"
"请先删除或解除关联数据"
)
elif detail:
message += f"{detail}"
super().__init__(
message,
context={
"detail": detail,
"referenced_table": referenced_table,
"constraint_name": constraint_name,
},
)
class DataTypeMismatchError(FormDataValidationError):
"""数据类型不匹配"""
error_code = "DATA_TYPE_MISMATCH"
def __init__(self, detail: str = ""):
msg = "数据类型不匹配,请检查输入数据格式"
if detail:
msg += f"{detail}"
super().__init__(msg, context={"detail": detail})
class DataTooLongError(FormDataValidationError):
"""数据长度超出字段限制"""
error_code = "DATA_TOO_LONG"
def __init__(self, column: str = "", max_length: int = 0):
msg = f"字段 '{column}' 的数据过长" if column else "数据长度超出限制"
if max_length:
msg += f"(最大 {max_length} 个字符)"
super().__init__(
msg,
context={"column": column, "max_length": max_length},
)
# =====================================================================
# 表结构 / 配置错误
# =====================================================================
class FormDataSchemaError(FormDataException):
"""表结构或配置相关错误基类"""
error_code = "SCHEMA_ERROR"
http_status = 400
class TableNotFoundError(FormDataSchemaError):
"""数据库表不存在"""
error_code = "TABLE_NOT_FOUND"
def __init__(self, table: str = ""):
msg = f"数据库表 {table} 不存在,请检查数据源配置" if table else "数据库表不存在"
super().__init__(msg, context={"table": table})
class ColumnNotFoundError(FormDataSchemaError):
"""数据库列不存在"""
error_code = "COLUMN_NOT_FOUND"
def __init__(self, column: str = "", table: str = ""):
msg = f"数据库字段 '{column}' 不存在" if column else "数据库字段不存在"
msg += ",请检查表单配置与数据库表结构是否一致"
super().__init__(msg, context={"column": column, "table": table})
# =====================================================================
# 连接相关
# =====================================================================
class FormDataConnectionError(FormDataException):
"""数据库连接相关错误基类"""
error_code = "CONNECTION_ERROR"
http_status = 503
class DatabaseConnectionError(FormDataConnectionError):
"""数据库连接失败或断开"""
error_code = "DB_CONNECTION_FAILED"
def __init__(self, detail: str = ""):
msg = "数据库连接异常,请稍后重试"
super().__init__(msg, context={"detail": detail})
class ConnectionPoolExhaustedError(FormDataConnectionError):
"""连接池耗尽"""
error_code = "CONNECTION_POOL_EXHAUSTED"
def __init__(self):
super().__init__(
"服务器繁忙(数据库连接池已满),请稍后重试",
)
class ConnectionTimeoutError(FormDataConnectionError):
"""连接超时"""
error_code = "CONNECTION_TIMEOUT"
def __init__(self):
super().__init__("数据库连接超时,请稍后重试")
# =====================================================================
# 并发相关
# =====================================================================
class FormDataConcurrencyError(FormDataException):
"""并发相关错误基类"""
error_code = "CONCURRENCY_ERROR"
http_status = 409
class DeadlockError(FormDataConcurrencyError):
"""死锁"""
error_code = "DEADLOCK"
def __init__(self):
super().__init__("操作冲突(死锁),请重试")
class LockTimeoutError(FormDataConcurrencyError):
"""锁等待超时"""
error_code = "LOCK_TIMEOUT"
def __init__(self):
super().__init__("操作等待超时,请稍后重试")
# =====================================================================
# 查询 / 其他
# =====================================================================
class QueryError(FormDataException):
"""SQL 查询构建或执行错误"""
error_code = "QUERY_ERROR"
http_status = 400
def __init__(self, detail: str = ""):
msg = "数据库查询异常,请检查表单配置是否正确"
super().__init__(msg, context={"detail": detail})
class InternalDatabaseError(FormDataException):
"""其他未分类的数据库内部错误"""
error_code = "INTERNAL_DB_ERROR"
http_status = 500
def __init__(self, detail: str = ""):
msg = "数据库操作失败,请联系管理员"
super().__init__(msg, context={"detail": detail})