infomankit 0.3.23__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- infoman/__init__.py +1 -0
- infoman/cli/README.md +378 -0
- infoman/cli/__init__.py +7 -0
- infoman/cli/commands/__init__.py +3 -0
- infoman/cli/commands/init.py +312 -0
- infoman/cli/scaffold.py +634 -0
- infoman/cli/templates/Makefile.template +132 -0
- infoman/cli/templates/app/__init__.py.template +3 -0
- infoman/cli/templates/app/app.py.template +4 -0
- infoman/cli/templates/app/models_base.py.template +18 -0
- infoman/cli/templates/app/models_entity_init.py.template +11 -0
- infoman/cli/templates/app/models_schemas_init.py.template +11 -0
- infoman/cli/templates/app/repository_init.py.template +11 -0
- infoman/cli/templates/app/routers_init.py.template +15 -0
- infoman/cli/templates/app/services_init.py.template +11 -0
- infoman/cli/templates/app/static_index.html.template +39 -0
- infoman/cli/templates/app/static_main.js.template +31 -0
- infoman/cli/templates/app/static_style.css.template +111 -0
- infoman/cli/templates/app/utils_init.py.template +11 -0
- infoman/cli/templates/config/.env.dev.template +43 -0
- infoman/cli/templates/config/.env.prod.template +43 -0
- infoman/cli/templates/config/README.md.template +28 -0
- infoman/cli/templates/docker/.dockerignore.template +60 -0
- infoman/cli/templates/docker/Dockerfile.template +47 -0
- infoman/cli/templates/docker/README.md.template +240 -0
- infoman/cli/templates/docker/docker-compose.yml.template +81 -0
- infoman/cli/templates/docker/mysql_custom.cnf.template +42 -0
- infoman/cli/templates/docker/mysql_init.sql.template +15 -0
- infoman/cli/templates/project/.env.example.template +1 -0
- infoman/cli/templates/project/.gitignore.template +60 -0
- infoman/cli/templates/project/Makefile.template +38 -0
- infoman/cli/templates/project/README.md.template +137 -0
- infoman/cli/templates/project/deploy.sh.template +97 -0
- infoman/cli/templates/project/main.py.template +10 -0
- infoman/cli/templates/project/manage.sh.template +97 -0
- infoman/cli/templates/project/pyproject.toml.template +47 -0
- infoman/cli/templates/project/service.sh.template +203 -0
- infoman/config/__init__.py +25 -0
- infoman/config/base.py +67 -0
- infoman/config/db_cache.py +237 -0
- infoman/config/db_relation.py +181 -0
- infoman/config/db_vector.py +39 -0
- infoman/config/jwt.py +16 -0
- infoman/config/llm.py +16 -0
- infoman/config/log.py +627 -0
- infoman/config/mq.py +26 -0
- infoman/config/settings.py +65 -0
- infoman/llm/__init__.py +0 -0
- infoman/llm/llm.py +297 -0
- infoman/logger/__init__.py +57 -0
- infoman/logger/context.py +191 -0
- infoman/logger/core.py +358 -0
- infoman/logger/filters.py +157 -0
- infoman/logger/formatters.py +138 -0
- infoman/logger/handlers.py +276 -0
- infoman/logger/metrics.py +160 -0
- infoman/performance/README.md +583 -0
- infoman/performance/__init__.py +19 -0
- infoman/performance/cli.py +215 -0
- infoman/performance/config.py +166 -0
- infoman/performance/reporter.py +519 -0
- infoman/performance/runner.py +303 -0
- infoman/performance/standards.py +222 -0
- infoman/service/__init__.py +8 -0
- infoman/service/app.py +67 -0
- infoman/service/core/__init__.py +0 -0
- infoman/service/core/auth.py +105 -0
- infoman/service/core/lifespan.py +132 -0
- infoman/service/core/monitor.py +57 -0
- infoman/service/core/response.py +37 -0
- infoman/service/exception/__init__.py +7 -0
- infoman/service/exception/error.py +274 -0
- infoman/service/exception/exception.py +25 -0
- infoman/service/exception/handler.py +238 -0
- infoman/service/infrastructure/__init__.py +8 -0
- infoman/service/infrastructure/base.py +212 -0
- infoman/service/infrastructure/db_cache/__init__.py +8 -0
- infoman/service/infrastructure/db_cache/manager.py +194 -0
- infoman/service/infrastructure/db_relation/__init__.py +41 -0
- infoman/service/infrastructure/db_relation/manager.py +300 -0
- infoman/service/infrastructure/db_relation/manager_pro.py +408 -0
- infoman/service/infrastructure/db_relation/mysql.py +52 -0
- infoman/service/infrastructure/db_relation/pgsql.py +54 -0
- infoman/service/infrastructure/db_relation/sqllite.py +25 -0
- infoman/service/infrastructure/db_vector/__init__.py +40 -0
- infoman/service/infrastructure/db_vector/manager.py +201 -0
- infoman/service/infrastructure/db_vector/qdrant.py +322 -0
- infoman/service/infrastructure/mq/__init__.py +15 -0
- infoman/service/infrastructure/mq/manager.py +178 -0
- infoman/service/infrastructure/mq/nats/__init__.py +0 -0
- infoman/service/infrastructure/mq/nats/nats_client.py +57 -0
- infoman/service/infrastructure/mq/nats/nats_event_router.py +25 -0
- infoman/service/launch.py +284 -0
- infoman/service/middleware/__init__.py +7 -0
- infoman/service/middleware/base.py +41 -0
- infoman/service/middleware/logging.py +51 -0
- infoman/service/middleware/rate_limit.py +301 -0
- infoman/service/middleware/request_id.py +21 -0
- infoman/service/middleware/white_list.py +24 -0
- infoman/service/models/__init__.py +8 -0
- infoman/service/models/base.py +441 -0
- infoman/service/models/type/embed.py +70 -0
- infoman/service/routers/__init__.py +18 -0
- infoman/service/routers/health_router.py +311 -0
- infoman/service/routers/monitor_router.py +44 -0
- infoman/service/utils/__init__.py +8 -0
- infoman/service/utils/cache/__init__.py +0 -0
- infoman/service/utils/cache/cache.py +192 -0
- infoman/service/utils/module_loader.py +10 -0
- infoman/service/utils/parse.py +10 -0
- infoman/service/utils/resolver/__init__.py +8 -0
- infoman/service/utils/resolver/base.py +47 -0
- infoman/service/utils/resolver/resp.py +102 -0
- infoman/service/vector/__init__.py +20 -0
- infoman/service/vector/base.py +56 -0
- infoman/service/vector/qdrant.py +125 -0
- infoman/service/vector/service.py +67 -0
- infoman/utils/__init__.py +2 -0
- infoman/utils/decorators/__init__.py +8 -0
- infoman/utils/decorators/cache.py +137 -0
- infoman/utils/decorators/retry.py +99 -0
- infoman/utils/decorators/safe_execute.py +99 -0
- infoman/utils/decorators/timing.py +99 -0
- infoman/utils/encryption/__init__.py +8 -0
- infoman/utils/encryption/aes.py +66 -0
- infoman/utils/encryption/ecc.py +108 -0
- infoman/utils/encryption/rsa.py +112 -0
- infoman/utils/file/__init__.py +0 -0
- infoman/utils/file/handler.py +22 -0
- infoman/utils/hash/__init__.py +0 -0
- infoman/utils/hash/hash.py +61 -0
- infoman/utils/http/__init__.py +8 -0
- infoman/utils/http/client.py +62 -0
- infoman/utils/http/info.py +94 -0
- infoman/utils/http/result.py +19 -0
- infoman/utils/notification/__init__.py +8 -0
- infoman/utils/notification/feishu.py +35 -0
- infoman/utils/text/__init__.py +8 -0
- infoman/utils/text/extractor.py +111 -0
- infomankit-0.3.23.dist-info/METADATA +632 -0
- infomankit-0.3.23.dist-info/RECORD +143 -0
- infomankit-0.3.23.dist-info/WHEEL +4 -0
- infomankit-0.3.23.dist-info/entry_points.txt +5 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# service/core/lifespan.py
|
|
2
|
+
"""
|
|
3
|
+
应用生命周期管理(精简版)
|
|
4
|
+
|
|
5
|
+
职责:
|
|
6
|
+
- 协调各个服务的启动和关闭
|
|
7
|
+
- 不包含具体的连接逻辑
|
|
8
|
+
- 支持可选依赖的优雅降级
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from contextlib import asynccontextmanager
|
|
12
|
+
from fastapi import FastAPI
|
|
13
|
+
from loguru import logger
|
|
14
|
+
|
|
15
|
+
from infoman.config import settings
|
|
16
|
+
|
|
17
|
+
# ========== 数据库(必需) ==========
|
|
18
|
+
if settings.USE_PRO_ORM:
|
|
19
|
+
from infoman.service.infrastructure.db_relation.manager_pro import db_manager
|
|
20
|
+
_DB_MANAGER_TYPE = "pro"
|
|
21
|
+
else:
|
|
22
|
+
from infoman.service.infrastructure.db_relation.manager import db_manager
|
|
23
|
+
_DB_MANAGER_TYPE = "basic"
|
|
24
|
+
|
|
25
|
+
# ========== Redis(可选) ==========
|
|
26
|
+
try:
|
|
27
|
+
from infoman.service.infrastructure.db_cache.manager import RedisManager
|
|
28
|
+
REDIS_AVAILABLE = True
|
|
29
|
+
except ImportError:
|
|
30
|
+
logger.warning("⚠️ Redis 依赖未安装,缓存功能将不可用 (需要: redis, fastapi-cache2)")
|
|
31
|
+
RedisManager = None
|
|
32
|
+
REDIS_AVAILABLE = False
|
|
33
|
+
|
|
34
|
+
# ========== 向量数据库(可选) ==========
|
|
35
|
+
try:
|
|
36
|
+
from infoman.service.infrastructure.db_vector.manager import VectorDBManager
|
|
37
|
+
VECTOR_AVAILABLE = True
|
|
38
|
+
except ImportError:
|
|
39
|
+
logger.warning("⚠️ 向量数据库依赖未安装,向量搜索功能将不可用 (需要: qdrant-client)")
|
|
40
|
+
VectorDBManager = None
|
|
41
|
+
VECTOR_AVAILABLE = False
|
|
42
|
+
|
|
43
|
+
# ========== 消息队列(可选) ==========
|
|
44
|
+
try:
|
|
45
|
+
from infoman.service.infrastructure.mq import NATSManager
|
|
46
|
+
MQ_AVAILABLE = True
|
|
47
|
+
except ImportError:
|
|
48
|
+
logger.warning("⚠️ 消息队列依赖未安装,NATS 功能将不可用 (需要: nats-py)")
|
|
49
|
+
NATSManager = None
|
|
50
|
+
MQ_AVAILABLE = False
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@asynccontextmanager
|
|
54
|
+
async def lifespan(app: FastAPI):
|
|
55
|
+
"""应用生命周期管理(支持可选依赖)"""
|
|
56
|
+
|
|
57
|
+
# ========== 启动 ==========
|
|
58
|
+
logger.info(f"🚀 应用启动中 [{settings.APP_NAME} v{settings.APP_VERSION}]")
|
|
59
|
+
logger.info(f" 环境: {settings.ENV}")
|
|
60
|
+
logger.info(f" 数据库管理器: {_DB_MANAGER_TYPE}")
|
|
61
|
+
logger.info(f" 可选功能: Redis={REDIS_AVAILABLE}, Vector={VECTOR_AVAILABLE}, MQ={MQ_AVAILABLE}")
|
|
62
|
+
|
|
63
|
+
# 初始化管理器(仅限已安装的)
|
|
64
|
+
managers = {}
|
|
65
|
+
|
|
66
|
+
# 数据库(必需)
|
|
67
|
+
managers['db'] = db_manager
|
|
68
|
+
app.state.db_manager = db_manager
|
|
69
|
+
|
|
70
|
+
# Redis(可选)
|
|
71
|
+
if REDIS_AVAILABLE:
|
|
72
|
+
redis_manager = RedisManager()
|
|
73
|
+
managers['redis'] = redis_manager
|
|
74
|
+
app.state.redis_manager = redis_manager
|
|
75
|
+
|
|
76
|
+
# 向量数据库(可选)
|
|
77
|
+
if VECTOR_AVAILABLE:
|
|
78
|
+
vector_manager = VectorDBManager()
|
|
79
|
+
managers['vector'] = vector_manager
|
|
80
|
+
app.state.vector_manager = vector_manager
|
|
81
|
+
|
|
82
|
+
# 消息队列(可选)
|
|
83
|
+
if MQ_AVAILABLE:
|
|
84
|
+
nats_manager = NATSManager()
|
|
85
|
+
managers['mq'] = nats_manager
|
|
86
|
+
app.state.nats_manager = nats_manager
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
# 1. 数据库
|
|
90
|
+
await db_manager.startup(app)
|
|
91
|
+
|
|
92
|
+
# 2. Redis(如果可用)
|
|
93
|
+
if 'redis' in managers:
|
|
94
|
+
await managers['redis'].startup(app)
|
|
95
|
+
|
|
96
|
+
# 3. 向量数据库(如果可用)
|
|
97
|
+
if 'vector' in managers:
|
|
98
|
+
await managers['vector'].startup(app)
|
|
99
|
+
|
|
100
|
+
# 4. 消息队列(如果可用)
|
|
101
|
+
if 'mq' in managers:
|
|
102
|
+
await managers['mq'].startup(app)
|
|
103
|
+
|
|
104
|
+
logger.success("✅ 所有服务启动完成")
|
|
105
|
+
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logger.error(f"❌ 服务启动失败: {e}")
|
|
108
|
+
raise
|
|
109
|
+
|
|
110
|
+
# ========== 运行 ==========
|
|
111
|
+
yield
|
|
112
|
+
|
|
113
|
+
# ========== 关闭 ==========
|
|
114
|
+
logger.info("⏹️ 应用关闭中...")
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
# 按相反顺序关闭(仅关闭已启动的)
|
|
118
|
+
if 'mq' in managers:
|
|
119
|
+
await managers['mq'].shutdown()
|
|
120
|
+
|
|
121
|
+
if 'vector' in managers:
|
|
122
|
+
await managers['vector'].shutdown()
|
|
123
|
+
|
|
124
|
+
if 'redis' in managers:
|
|
125
|
+
await managers['redis'].shutdown()
|
|
126
|
+
|
|
127
|
+
await db_manager.shutdown()
|
|
128
|
+
|
|
129
|
+
logger.success("✅ 所有服务已关闭")
|
|
130
|
+
|
|
131
|
+
except Exception as e:
|
|
132
|
+
logger.error(f"❌ 服务关闭失败: {e}")
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from prometheus_fastapi_instrumentator import Instrumentator, metrics
|
|
2
|
+
from prometheus_client import Counter, Histogram, Gauge
|
|
3
|
+
|
|
4
|
+
# ===== 1. HTTP 指标(自动收集)=====
|
|
5
|
+
instrumentator = Instrumentator(
|
|
6
|
+
should_group_status_codes=True,
|
|
7
|
+
should_ignore_untemplated=True,
|
|
8
|
+
should_respect_env_var=True,
|
|
9
|
+
should_instrument_requests_inprogress=True,
|
|
10
|
+
excluded_handlers=["/health", "/metrics", "/doc", "/redoc", "/openapi.json"],
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
instrumentator.add(metrics.default())
|
|
14
|
+
instrumentator.add(metrics.request_size())
|
|
15
|
+
instrumentator.add(metrics.response_size())
|
|
16
|
+
|
|
17
|
+
# ===== 2. 业务指标(手动收集)=====
|
|
18
|
+
|
|
19
|
+
# 用户操作
|
|
20
|
+
user_operations = Counter(
|
|
21
|
+
"user_operations_total", "Total user operations", ["operation_type", "status"]
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# 数据库查询
|
|
25
|
+
db_query_duration = Histogram(
|
|
26
|
+
"db_query_duration_seconds",
|
|
27
|
+
"Database query duration",
|
|
28
|
+
["query_type"],
|
|
29
|
+
buckets=[0.001, 0.01, 0.05, 0.1, 0.5, 1.0, 2.5, 5.0],
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# 缓存
|
|
33
|
+
cache_hits = Counter("cache_hits_total", "Cache hits", ["cache_type"])
|
|
34
|
+
cache_misses = Counter("cache_misses_total", "Cache misses", ["cache_type"])
|
|
35
|
+
|
|
36
|
+
# 连接数
|
|
37
|
+
active_db_connections = Gauge("active_db_connections", "Active database connections")
|
|
38
|
+
active_redis_connections = Gauge("active_redis_connections", "Active Redis connections")
|
|
39
|
+
|
|
40
|
+
# 队列
|
|
41
|
+
task_queue_length = Gauge("task_queue_length", "Task queue length")
|
|
42
|
+
|
|
43
|
+
# 在线用户
|
|
44
|
+
online_users = Gauge("online_users", "Online users count")
|
|
45
|
+
|
|
46
|
+
# ===== 3. 导出所有指标(方便使用)=====
|
|
47
|
+
__all__ = [
|
|
48
|
+
"instrumentator",
|
|
49
|
+
"user_operations",
|
|
50
|
+
"db_query_duration",
|
|
51
|
+
"cache_hits",
|
|
52
|
+
"cache_misses",
|
|
53
|
+
"active_db_connections",
|
|
54
|
+
"active_redis_connections",
|
|
55
|
+
"task_queue_length",
|
|
56
|
+
"online_users",
|
|
57
|
+
]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# -*- coding:utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
# Time :2023/12/8 18:23
|
|
4
|
+
# Author :Maxwell
|
|
5
|
+
# version :python 3.9
|
|
6
|
+
# Description:
|
|
7
|
+
"""
|
|
8
|
+
from infoman.service.exception.exception import AppError
|
|
9
|
+
from infoman.config import settings as config
|
|
10
|
+
from fastapi.responses import ORJSONResponse
|
|
11
|
+
import orjson
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ProRJSONResponse(ORJSONResponse):
|
|
15
|
+
def render(self, content) -> bytes:
|
|
16
|
+
return orjson.dumps(
|
|
17
|
+
content,
|
|
18
|
+
option=(
|
|
19
|
+
orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_UTC_Z
|
|
20
|
+
),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def response(code, msg, data=None):
|
|
25
|
+
result = {"code": code, "message": msg, "data": data}
|
|
26
|
+
return result
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def success(data=None, msg=""):
|
|
30
|
+
return response(200, msg, data)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def failed(error: AppError):
|
|
34
|
+
msg = error.message_en
|
|
35
|
+
if not config.DEFAULT_LANGUAGE_IS_EN:
|
|
36
|
+
msg = error.message
|
|
37
|
+
return response(code=error.code, msg=msg)
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Optional, Dict, Any
|
|
4
|
+
from http import HTTPStatus
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class ErrorProperties:
|
|
9
|
+
code: int
|
|
10
|
+
message: str
|
|
11
|
+
message_en: str
|
|
12
|
+
status_code: int = HTTPStatus.INTERNAL_SERVER_ERROR
|
|
13
|
+
details: Optional[Dict[str, Any]] = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AppError(Enum):
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def code(self) -> int:
|
|
20
|
+
return self.value.code
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def message(self) -> str:
|
|
24
|
+
return self.value.message
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def message_en(self) -> str:
|
|
28
|
+
return self.value.message_en
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def status_code(self) -> int:
|
|
32
|
+
return self.value.status_code
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def details(self) -> Optional[Dict[str, Any]]:
|
|
36
|
+
return self.value.details
|
|
37
|
+
|
|
38
|
+
def with_details(self, details: Dict[str, Any]) -> ErrorProperties:
|
|
39
|
+
return ErrorProperties(
|
|
40
|
+
code=self.code,
|
|
41
|
+
message=self.message,
|
|
42
|
+
message_en=self.message_en,
|
|
43
|
+
status_code=self.status_code,
|
|
44
|
+
details=details,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class AppSystemError(AppError):
|
|
49
|
+
UNKNOWN_ERROR = ErrorProperties(
|
|
50
|
+
100000, "系统未知异常", "Unknown system error", HTTPStatus.INTERNAL_SERVER_ERROR
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
SYSTEM_ERROR = ErrorProperties(
|
|
54
|
+
100001,
|
|
55
|
+
"系统内部错误",
|
|
56
|
+
"Internal server error",
|
|
57
|
+
HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
TIMEOUT_ERROR = ErrorProperties(
|
|
61
|
+
100002, "系统处理超时", "System processing timeout", HTTPStatus.GATEWAY_TIMEOUT
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
SERVICE_UNAVAILABLE = ErrorProperties(
|
|
65
|
+
100003,
|
|
66
|
+
"服务暂时不可用",
|
|
67
|
+
"Service temporarily unavailable",
|
|
68
|
+
HTTPStatus.SERVICE_UNAVAILABLE,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
RESOURCE_EXHAUSTED = ErrorProperties(
|
|
72
|
+
100004,
|
|
73
|
+
"系统资源不足",
|
|
74
|
+
"System resources exhausted",
|
|
75
|
+
HTTPStatus.TOO_MANY_REQUESTS,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
CONFIGURATION_ERROR = ErrorProperties(
|
|
79
|
+
100005,
|
|
80
|
+
"系统配置错误",
|
|
81
|
+
"System configuration error",
|
|
82
|
+
HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class RequestError(AppError):
|
|
87
|
+
VALIDATION_ERROR = ErrorProperties(
|
|
88
|
+
200000,
|
|
89
|
+
"请求数据验证失败",
|
|
90
|
+
"Request data validation failed",
|
|
91
|
+
HTTPStatus.BAD_REQUEST,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
INVALID_PARAMETER = ErrorProperties(
|
|
95
|
+
200001, "无效的请求参数", "Invalid request parameter", HTTPStatus.BAD_REQUEST
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
MISSING_PARAMETER = ErrorProperties(
|
|
99
|
+
200002, "缺少必要参数", "Missing required parameter", HTTPStatus.BAD_REQUEST
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
INVALID_FORMAT = ErrorProperties(
|
|
103
|
+
200003, "请求格式错误", "Invalid request format", HTTPStatus.BAD_REQUEST
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
REQUEST_TOO_LARGE = ErrorProperties(
|
|
107
|
+
200004,
|
|
108
|
+
"请求体过大",
|
|
109
|
+
"Request body too large",
|
|
110
|
+
HTTPStatus.REQUEST_ENTITY_TOO_LARGE,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
RATE_LIMITED = ErrorProperties(
|
|
114
|
+
200005, "请求频率超限", "Request rate limited", HTTPStatus.TOO_MANY_REQUESTS
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
UNSUPPORTED_MEDIA_TYPE = ErrorProperties(
|
|
118
|
+
200006,
|
|
119
|
+
"不支持的媒体类型",
|
|
120
|
+
"Unsupported media type",
|
|
121
|
+
HTTPStatus.UNSUPPORTED_MEDIA_TYPE,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class DatabaseError(AppError):
|
|
126
|
+
VALIDATION_ERROR = ErrorProperties(
|
|
127
|
+
300000, "数据验证失败", "Data validation failed", HTTPStatus.BAD_REQUEST
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
INTEGRITY_ERROR = ErrorProperties(
|
|
131
|
+
300001,
|
|
132
|
+
"数据完整性约束冲突",
|
|
133
|
+
"Data integrity constraint violation",
|
|
134
|
+
HTTPStatus.CONFLICT,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
RECORD_NOT_FOUND = ErrorProperties(
|
|
138
|
+
300002, "记录不存在", "Record not found", HTTPStatus.NOT_FOUND
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
DUPLICATE_ENTRY = ErrorProperties(
|
|
142
|
+
300003, "记录已存在", "Duplicate record", HTTPStatus.CONFLICT
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
OPERATIONAL_ERROR = ErrorProperties(
|
|
146
|
+
300004,
|
|
147
|
+
"数据库操作错误",
|
|
148
|
+
"Database operational error",
|
|
149
|
+
HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
CONNECTION_ERROR = ErrorProperties(
|
|
153
|
+
300005,
|
|
154
|
+
"数据库连接错误",
|
|
155
|
+
"Database connection error",
|
|
156
|
+
HTTPStatus.SERVICE_UNAVAILABLE,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
TRANSACTION_ERROR = ErrorProperties(
|
|
160
|
+
300006,
|
|
161
|
+
"事务处理错误",
|
|
162
|
+
"Transaction processing error",
|
|
163
|
+
HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
QUERY_TIMEOUT = ErrorProperties(
|
|
167
|
+
300007, "查询超时", "Query timeout", HTTPStatus.GATEWAY_TIMEOUT
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class BusinessError(AppError):
|
|
172
|
+
|
|
173
|
+
INVALID_OPERATION = ErrorProperties(
|
|
174
|
+
400000, "无效的操作", "Invalid operation", HTTPStatus.BAD_REQUEST
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
STATE_CONFLICT = ErrorProperties(
|
|
178
|
+
400001, "状态冲突", "State conflict", HTTPStatus.CONFLICT
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
RESOURCE_LOCKED = ErrorProperties(
|
|
182
|
+
400002, "资源已锁定", "Resource locked", HTTPStatus.LOCKED
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
QUOTA_EXCEEDED = ErrorProperties(
|
|
186
|
+
400003, "配额超限", "Quota exceeded", HTTPStatus.FORBIDDEN
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
PAYMENT_REQUIRED = ErrorProperties(
|
|
190
|
+
400004, "需要付款", "Payment required", HTTPStatus.PAYMENT_REQUIRED
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
BUSINESS_RULE_VIOLATION = ErrorProperties(
|
|
194
|
+
400005, "违反业务规则", "Business rule violation", HTTPStatus.BAD_REQUEST
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class SecurityError(AppError):
|
|
199
|
+
"""
|
|
200
|
+
安全相关错误
|
|
201
|
+
|
|
202
|
+
包括认证、授权、访问控制等错误
|
|
203
|
+
错误代码范围:500000-599999
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
UNAUTHORIZED = ErrorProperties(
|
|
207
|
+
500000, "未授权访问", "Unauthorized access", HTTPStatus.UNAUTHORIZED
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
FORBIDDEN = ErrorProperties(
|
|
211
|
+
500001, "禁止访问", "Access forbidden", HTTPStatus.FORBIDDEN
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
INVALID_CREDENTIALS = ErrorProperties(
|
|
215
|
+
500002, "无效的凭证", "Invalid credentials", HTTPStatus.UNAUTHORIZED
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
TOKEN_EXPIRED = ErrorProperties(
|
|
219
|
+
500003, "令牌已过期", "Token expired", HTTPStatus.UNAUTHORIZED
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
INVALID_TOKEN = ErrorProperties(
|
|
223
|
+
500004, "无效的令牌", "Invalid token", HTTPStatus.UNAUTHORIZED
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
PERMISSION_DENIED = ErrorProperties(
|
|
227
|
+
500005, "权限不足", "Permission denied", HTTPStatus.FORBIDDEN
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
ACCOUNT_LOCKED = ErrorProperties(
|
|
231
|
+
500006, "账户已锁定", "Account locked", HTTPStatus.FORBIDDEN
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
IP_RESTRICTED = ErrorProperties(
|
|
235
|
+
500007, "IP地址受限", "IP address restricted", HTTPStatus.FORBIDDEN
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class ExternalServiceError(AppError):
|
|
240
|
+
"""
|
|
241
|
+
外部服务错误
|
|
242
|
+
|
|
243
|
+
包括第三方API、外部依赖服务等错误
|
|
244
|
+
错误代码范围:600000-699999
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
SERVICE_UNAVAILABLE = ErrorProperties(
|
|
248
|
+
600000, "外部服务不可用", "External service unavailable", HTTPStatus.BAD_GATEWAY
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
REQUEST_FAILED = ErrorProperties(
|
|
252
|
+
600001,
|
|
253
|
+
"外部服务请求失败",
|
|
254
|
+
"External service request failed",
|
|
255
|
+
HTTPStatus.BAD_GATEWAY,
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
RESPONSE_ERROR = ErrorProperties(
|
|
259
|
+
600002,
|
|
260
|
+
"外部服务响应错误",
|
|
261
|
+
"External service response error",
|
|
262
|
+
HTTPStatus.BAD_GATEWAY,
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
TIMEOUT = ErrorProperties(
|
|
266
|
+
600003, "外部服务超时", "External service timeout", HTTPStatus.GATEWAY_TIMEOUT
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
INVALID_RESPONSE = ErrorProperties(
|
|
270
|
+
600004,
|
|
271
|
+
"外部服务返回无效数据",
|
|
272
|
+
"Invalid data returned from external service",
|
|
273
|
+
HTTPStatus.BAD_GATEWAY,
|
|
274
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# -*-coding:utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
# Time :2025/6/21 21:51
|
|
6
|
+
# Author :Maxwell
|
|
7
|
+
# Description:
|
|
8
|
+
"""
|
|
9
|
+
from infoman.service.exception.error import AppError
|
|
10
|
+
from infoman.config.settings import settings
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AppException(Exception):
|
|
14
|
+
|
|
15
|
+
def __init__(self, error: AppError):
|
|
16
|
+
self.error_code = error.code
|
|
17
|
+
self.message = error.message_en
|
|
18
|
+
if not settings.DEFAULT_LANGUAGE_IS_EN:
|
|
19
|
+
self.message = error.message
|
|
20
|
+
super().__init__(error.message)
|
|
21
|
+
|
|
22
|
+
def with_content(self, place_holder, content):
|
|
23
|
+
if self.message:
|
|
24
|
+
self.message = self.message.replace(place_holder, content)
|
|
25
|
+
return self
|