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.
Files changed (143) hide show
  1. infoman/__init__.py +1 -0
  2. infoman/cli/README.md +378 -0
  3. infoman/cli/__init__.py +7 -0
  4. infoman/cli/commands/__init__.py +3 -0
  5. infoman/cli/commands/init.py +312 -0
  6. infoman/cli/scaffold.py +634 -0
  7. infoman/cli/templates/Makefile.template +132 -0
  8. infoman/cli/templates/app/__init__.py.template +3 -0
  9. infoman/cli/templates/app/app.py.template +4 -0
  10. infoman/cli/templates/app/models_base.py.template +18 -0
  11. infoman/cli/templates/app/models_entity_init.py.template +11 -0
  12. infoman/cli/templates/app/models_schemas_init.py.template +11 -0
  13. infoman/cli/templates/app/repository_init.py.template +11 -0
  14. infoman/cli/templates/app/routers_init.py.template +15 -0
  15. infoman/cli/templates/app/services_init.py.template +11 -0
  16. infoman/cli/templates/app/static_index.html.template +39 -0
  17. infoman/cli/templates/app/static_main.js.template +31 -0
  18. infoman/cli/templates/app/static_style.css.template +111 -0
  19. infoman/cli/templates/app/utils_init.py.template +11 -0
  20. infoman/cli/templates/config/.env.dev.template +43 -0
  21. infoman/cli/templates/config/.env.prod.template +43 -0
  22. infoman/cli/templates/config/README.md.template +28 -0
  23. infoman/cli/templates/docker/.dockerignore.template +60 -0
  24. infoman/cli/templates/docker/Dockerfile.template +47 -0
  25. infoman/cli/templates/docker/README.md.template +240 -0
  26. infoman/cli/templates/docker/docker-compose.yml.template +81 -0
  27. infoman/cli/templates/docker/mysql_custom.cnf.template +42 -0
  28. infoman/cli/templates/docker/mysql_init.sql.template +15 -0
  29. infoman/cli/templates/project/.env.example.template +1 -0
  30. infoman/cli/templates/project/.gitignore.template +60 -0
  31. infoman/cli/templates/project/Makefile.template +38 -0
  32. infoman/cli/templates/project/README.md.template +137 -0
  33. infoman/cli/templates/project/deploy.sh.template +97 -0
  34. infoman/cli/templates/project/main.py.template +10 -0
  35. infoman/cli/templates/project/manage.sh.template +97 -0
  36. infoman/cli/templates/project/pyproject.toml.template +47 -0
  37. infoman/cli/templates/project/service.sh.template +203 -0
  38. infoman/config/__init__.py +25 -0
  39. infoman/config/base.py +67 -0
  40. infoman/config/db_cache.py +237 -0
  41. infoman/config/db_relation.py +181 -0
  42. infoman/config/db_vector.py +39 -0
  43. infoman/config/jwt.py +16 -0
  44. infoman/config/llm.py +16 -0
  45. infoman/config/log.py +627 -0
  46. infoman/config/mq.py +26 -0
  47. infoman/config/settings.py +65 -0
  48. infoman/llm/__init__.py +0 -0
  49. infoman/llm/llm.py +297 -0
  50. infoman/logger/__init__.py +57 -0
  51. infoman/logger/context.py +191 -0
  52. infoman/logger/core.py +358 -0
  53. infoman/logger/filters.py +157 -0
  54. infoman/logger/formatters.py +138 -0
  55. infoman/logger/handlers.py +276 -0
  56. infoman/logger/metrics.py +160 -0
  57. infoman/performance/README.md +583 -0
  58. infoman/performance/__init__.py +19 -0
  59. infoman/performance/cli.py +215 -0
  60. infoman/performance/config.py +166 -0
  61. infoman/performance/reporter.py +519 -0
  62. infoman/performance/runner.py +303 -0
  63. infoman/performance/standards.py +222 -0
  64. infoman/service/__init__.py +8 -0
  65. infoman/service/app.py +67 -0
  66. infoman/service/core/__init__.py +0 -0
  67. infoman/service/core/auth.py +105 -0
  68. infoman/service/core/lifespan.py +132 -0
  69. infoman/service/core/monitor.py +57 -0
  70. infoman/service/core/response.py +37 -0
  71. infoman/service/exception/__init__.py +7 -0
  72. infoman/service/exception/error.py +274 -0
  73. infoman/service/exception/exception.py +25 -0
  74. infoman/service/exception/handler.py +238 -0
  75. infoman/service/infrastructure/__init__.py +8 -0
  76. infoman/service/infrastructure/base.py +212 -0
  77. infoman/service/infrastructure/db_cache/__init__.py +8 -0
  78. infoman/service/infrastructure/db_cache/manager.py +194 -0
  79. infoman/service/infrastructure/db_relation/__init__.py +41 -0
  80. infoman/service/infrastructure/db_relation/manager.py +300 -0
  81. infoman/service/infrastructure/db_relation/manager_pro.py +408 -0
  82. infoman/service/infrastructure/db_relation/mysql.py +52 -0
  83. infoman/service/infrastructure/db_relation/pgsql.py +54 -0
  84. infoman/service/infrastructure/db_relation/sqllite.py +25 -0
  85. infoman/service/infrastructure/db_vector/__init__.py +40 -0
  86. infoman/service/infrastructure/db_vector/manager.py +201 -0
  87. infoman/service/infrastructure/db_vector/qdrant.py +322 -0
  88. infoman/service/infrastructure/mq/__init__.py +15 -0
  89. infoman/service/infrastructure/mq/manager.py +178 -0
  90. infoman/service/infrastructure/mq/nats/__init__.py +0 -0
  91. infoman/service/infrastructure/mq/nats/nats_client.py +57 -0
  92. infoman/service/infrastructure/mq/nats/nats_event_router.py +25 -0
  93. infoman/service/launch.py +284 -0
  94. infoman/service/middleware/__init__.py +7 -0
  95. infoman/service/middleware/base.py +41 -0
  96. infoman/service/middleware/logging.py +51 -0
  97. infoman/service/middleware/rate_limit.py +301 -0
  98. infoman/service/middleware/request_id.py +21 -0
  99. infoman/service/middleware/white_list.py +24 -0
  100. infoman/service/models/__init__.py +8 -0
  101. infoman/service/models/base.py +441 -0
  102. infoman/service/models/type/embed.py +70 -0
  103. infoman/service/routers/__init__.py +18 -0
  104. infoman/service/routers/health_router.py +311 -0
  105. infoman/service/routers/monitor_router.py +44 -0
  106. infoman/service/utils/__init__.py +8 -0
  107. infoman/service/utils/cache/__init__.py +0 -0
  108. infoman/service/utils/cache/cache.py +192 -0
  109. infoman/service/utils/module_loader.py +10 -0
  110. infoman/service/utils/parse.py +10 -0
  111. infoman/service/utils/resolver/__init__.py +8 -0
  112. infoman/service/utils/resolver/base.py +47 -0
  113. infoman/service/utils/resolver/resp.py +102 -0
  114. infoman/service/vector/__init__.py +20 -0
  115. infoman/service/vector/base.py +56 -0
  116. infoman/service/vector/qdrant.py +125 -0
  117. infoman/service/vector/service.py +67 -0
  118. infoman/utils/__init__.py +2 -0
  119. infoman/utils/decorators/__init__.py +8 -0
  120. infoman/utils/decorators/cache.py +137 -0
  121. infoman/utils/decorators/retry.py +99 -0
  122. infoman/utils/decorators/safe_execute.py +99 -0
  123. infoman/utils/decorators/timing.py +99 -0
  124. infoman/utils/encryption/__init__.py +8 -0
  125. infoman/utils/encryption/aes.py +66 -0
  126. infoman/utils/encryption/ecc.py +108 -0
  127. infoman/utils/encryption/rsa.py +112 -0
  128. infoman/utils/file/__init__.py +0 -0
  129. infoman/utils/file/handler.py +22 -0
  130. infoman/utils/hash/__init__.py +0 -0
  131. infoman/utils/hash/hash.py +61 -0
  132. infoman/utils/http/__init__.py +8 -0
  133. infoman/utils/http/client.py +62 -0
  134. infoman/utils/http/info.py +94 -0
  135. infoman/utils/http/result.py +19 -0
  136. infoman/utils/notification/__init__.py +8 -0
  137. infoman/utils/notification/feishu.py +35 -0
  138. infoman/utils/text/__init__.py +8 -0
  139. infoman/utils/text/extractor.py +111 -0
  140. infomankit-0.3.23.dist-info/METADATA +632 -0
  141. infomankit-0.3.23.dist-info/RECORD +143 -0
  142. infomankit-0.3.23.dist-info/WHEEL +4 -0
  143. infomankit-0.3.23.dist-info/entry_points.txt +5 -0
@@ -0,0 +1,10 @@
1
+ from infoman.service.launch import serve
2
+
3
+
4
+ if __name__ == "__main__":
5
+ serve(
6
+ app_target="app.app:application",
7
+ server="granian",
8
+ reload=False,
9
+ workers=1
10
+ )
@@ -0,0 +1,97 @@
1
+ #!/bin/bash
2
+
3
+ # Color definitions
4
+ RED='\033[0;31m'
5
+ GREEN='\033[0;32m'
6
+ YELLOW='\033[1;33m'
7
+ BLUE='\033[0;34m'
8
+ NC='\033[0m' # No Color
9
+
10
+ # Print colored message
11
+ print_message() {{
12
+ local color=$1
13
+ local message=$2
14
+ echo -e "${{color}}${{message}}${{NC}}"
15
+ }}
16
+
17
+ # Print usage
18
+ print_usage() {{
19
+ echo "Usage: ./manage.sh [command]"
20
+ echo ""
21
+ echo "Available commands:"
22
+ echo " dev - Start development server"
23
+ echo " test - Run tests"
24
+ echo " lint - Run linter"
25
+ echo " format - Format code"
26
+ echo " clean - Clean temporary files"
27
+ echo " help - Show this help message"
28
+ }}
29
+
30
+ # Development server
31
+ cmd_dev() {{
32
+ print_message "$BLUE" "Starting development server..."
33
+ infoman-serve run app.app:app --reload --host 0.0.0.0 --port 8000
34
+ }}
35
+
36
+ # Run tests
37
+ cmd_test() {{
38
+ print_message "$BLUE" "Running tests..."
39
+ pytest tests/ -v --cov=app
40
+ }}
41
+
42
+ # Run linter
43
+ cmd_lint() {{
44
+ print_message "$BLUE" "Running linter..."
45
+ ruff check .
46
+ mypy app/
47
+ }}
48
+
49
+ # Format code
50
+ cmd_format() {{
51
+ print_message "$BLUE" "Formatting code..."
52
+ black .
53
+ ruff check --fix .
54
+ print_message "$GREEN" "Code formatted successfully"
55
+ }}
56
+
57
+ # Clean temporary files
58
+ cmd_clean() {{
59
+ print_message "$BLUE" "Cleaning temporary files..."
60
+ find . -type d -name "__pycache__" -exec rm -rf {{}} + 2>/dev/null
61
+ find . -type f -name "*.pyc" -delete 2>/dev/null
62
+ find . -type f -name "*.pyo" -delete 2>/dev/null
63
+ find . -type d -name "*.egg-info" -exec rm -rf {{}} + 2>/dev/null
64
+ find . -type d -name ".pytest_cache" -exec rm -rf {{}} + 2>/dev/null
65
+ find . -type d -name ".ruff_cache" -exec rm -rf {{}} + 2>/dev/null
66
+ find . -type d -name ".mypy_cache" -exec rm -rf {{}} + 2>/dev/null
67
+ rm -rf dist/ build/ 2>/dev/null
68
+ print_message "$GREEN" "Cleanup completed"
69
+ }}
70
+
71
+ # Main command dispatcher
72
+ case "$1" in
73
+ dev)
74
+ cmd_dev
75
+ ;;
76
+ test)
77
+ cmd_test
78
+ ;;
79
+ lint)
80
+ cmd_lint
81
+ ;;
82
+ format)
83
+ cmd_format
84
+ ;;
85
+ clean)
86
+ cmd_clean
87
+ ;;
88
+ help|--help|-h|"")
89
+ print_usage
90
+ ;;
91
+ *)
92
+ print_message "$RED" "Error: Unknown command '$1'"
93
+ echo ""
94
+ print_usage
95
+ exit 1
96
+ ;;
97
+ esac
@@ -0,0 +1,47 @@
1
+ [project]
2
+ name = "{project_name}"
3
+ version = "0.1.0"
4
+ description = "FastAPI application built with infomankit"
5
+ requires-python = ">=3.11"
6
+ dependencies = [
7
+ "infomankit>=0.3.18",
8
+ ]
9
+
10
+ [project.optional-dependencies]
11
+ dev = [
12
+ "pytest>=7.4.0",
13
+ "pytest-asyncio>=0.21.0",
14
+ "pytest-cov>=4.1.0",
15
+ "black>=23.11.0",
16
+ "ruff>=0.1.6",
17
+ "mypy>=1.7.0",
18
+ ]
19
+
20
+ [build-system]
21
+ requires = ["setuptools>=68.0"]
22
+ build-backend = "setuptools.build_meta"
23
+
24
+ [tool.black]
25
+ line-length = 100
26
+ target-version = ["py311"]
27
+
28
+ [tool.ruff]
29
+ line-length = 100
30
+ target-version = "py311"
31
+
32
+ [tool.ruff.lint]
33
+ select = ["E", "F", "I", "N", "W"]
34
+ ignore = ["E501"]
35
+
36
+ [tool.mypy]
37
+ python_version = "3.11"
38
+ warn_return_any = true
39
+ warn_unused_configs = true
40
+ disallow_untyped_defs = true
41
+
42
+ [tool.pytest.ini_options]
43
+ testpaths = ["tests"]
44
+ python_files = "test_*.py"
45
+ python_classes = "Test*"
46
+ python_functions = "test_*"
47
+ asyncio_mode = "auto"
@@ -0,0 +1,203 @@
1
+ #!/bin/bash
2
+
3
+ # {project_name} Service Management Script
4
+ # Manages the application as a background service
5
+
6
+ set -e
7
+
8
+ PROJECT_NAME="{project_name}"
9
+ PID_FILE=".app.pid"
10
+ LOG_FILE="logs/app.log"
11
+ ERROR_LOG_FILE="logs/app.error.log"
12
+
13
+ # Color definitions
14
+ RED='\033[0;31m'
15
+ GREEN='\033[0;32m'
16
+ YELLOW='\033[1;33m'
17
+ BLUE='\033[0;34m'
18
+ NC='\033[0m' # No Color
19
+
20
+ # Print colored message
21
+ print_message() {{
22
+ local color=$1
23
+ local message=$2
24
+ echo -e "${{color}}${{message}}${{NC}}"
25
+ }}
26
+
27
+ # Check if service is running
28
+ is_running() {{
29
+ if [ -f "$PID_FILE" ]; then
30
+ local pid=$(cat "$PID_FILE")
31
+ if kill -0 "$pid" 2>/dev/null; then
32
+ return 0
33
+ else
34
+ # PID file exists but process is dead, clean up
35
+ rm -f "$PID_FILE"
36
+ return 1
37
+ fi
38
+ fi
39
+ return 1
40
+ }}
41
+
42
+ # Start service
43
+ cmd_start() {{
44
+ if is_running; then
45
+ print_message "$YELLOW" "Service is already running (PID: $(cat "$PID_FILE"))"
46
+ exit 1
47
+ fi
48
+
49
+ print_message "$BLUE" "Starting $PROJECT_NAME service..."
50
+
51
+ # Create logs directory if not exists
52
+ mkdir -p logs
53
+
54
+ # Start service in background
55
+ nohup python main.py > "$LOG_FILE" 2> "$ERROR_LOG_FILE" &
56
+ local pid=$!
57
+ echo $pid > "$PID_FILE"
58
+
59
+ # Wait a moment and check if it's still running
60
+ sleep 2
61
+ if is_running; then
62
+ print_message "$GREEN" "Service started successfully (PID: $pid)"
63
+ print_message "$BLUE" "Logs: $LOG_FILE"
64
+ else
65
+ print_message "$RED" "Service failed to start. Check $ERROR_LOG_FILE for details"
66
+ rm -f "$PID_FILE"
67
+ exit 1
68
+ fi
69
+ }}
70
+
71
+ # Stop service
72
+ cmd_stop() {{
73
+ if ! is_running; then
74
+ print_message "$YELLOW" "Service is not running"
75
+ exit 1
76
+ fi
77
+
78
+ local pid=$(cat "$PID_FILE")
79
+ print_message "$BLUE" "Stopping $PROJECT_NAME service (PID: $pid)..."
80
+
81
+ # Try graceful shutdown first
82
+ kill -TERM "$pid" 2>/dev/null || true
83
+
84
+ # Wait up to 10 seconds for graceful shutdown
85
+ local count=0
86
+ while kill -0 "$pid" 2>/dev/null && [ $count -lt 10 ]; do
87
+ sleep 1
88
+ count=$((count + 1))
89
+ done
90
+
91
+ # Force kill if still running
92
+ if kill -0 "$pid" 2>/dev/null; then
93
+ print_message "$YELLOW" "Graceful shutdown failed, forcing kill..."
94
+ kill -9 "$pid" 2>/dev/null || true
95
+ fi
96
+
97
+ rm -f "$PID_FILE"
98
+ print_message "$GREEN" "Service stopped"
99
+ }}
100
+
101
+ # Restart service
102
+ cmd_restart() {{
103
+ print_message "$BLUE" "Restarting $PROJECT_NAME service..."
104
+ if is_running; then
105
+ cmd_stop
106
+ sleep 1
107
+ fi
108
+ cmd_start
109
+ }}
110
+
111
+ # Show service status
112
+ cmd_status() {{
113
+ if is_running; then
114
+ local pid=$(cat "$PID_FILE")
115
+ print_message "$GREEN" "Service is running (PID: $pid)"
116
+
117
+ # Show process info
118
+ if command -v ps >/dev/null 2>&1; then
119
+ echo ""
120
+ ps -p "$pid" -o pid,ppid,user,%cpu,%mem,etime,command 2>/dev/null || true
121
+ fi
122
+ else
123
+ print_message "$RED" "Service is not running"
124
+ exit 1
125
+ fi
126
+ }}
127
+
128
+ # Show logs
129
+ cmd_logs() {{
130
+ if [ ! -f "$LOG_FILE" ]; then
131
+ print_message "$YELLOW" "Log file not found: $LOG_FILE"
132
+ exit 1
133
+ fi
134
+
135
+ print_message "$BLUE" "Showing logs (Ctrl+C to exit)..."
136
+ tail -f "$LOG_FILE"
137
+ }}
138
+
139
+ # Show error logs
140
+ cmd_errors() {{
141
+ if [ ! -f "$ERROR_LOG_FILE" ]; then
142
+ print_message "$YELLOW" "Error log file not found: $ERROR_LOG_FILE"
143
+ exit 1
144
+ fi
145
+
146
+ print_message "$BLUE" "Showing error logs (Ctrl+C to exit)..."
147
+ tail -f "$ERROR_LOG_FILE"
148
+ }}
149
+
150
+ # Print usage
151
+ print_usage() {{
152
+ cat << EOF
153
+ ${{BLUE}}$PROJECT_NAME Service Manager${{NC}}
154
+
155
+ Usage: ./service.sh [command]
156
+
157
+ Commands:
158
+ start Start the service in background
159
+ stop Stop the service
160
+ restart Restart the service
161
+ status Show service status
162
+ logs Show application logs (follow mode)
163
+ errors Show error logs (follow mode)
164
+ help Show this help message
165
+
166
+ Examples:
167
+ ./service.sh start
168
+ ./service.sh status
169
+ ./service.sh logs
170
+
171
+ EOF
172
+ }}
173
+
174
+ # Main command dispatcher
175
+ case "$1" in
176
+ start)
177
+ cmd_start
178
+ ;;
179
+ stop)
180
+ cmd_stop
181
+ ;;
182
+ restart)
183
+ cmd_restart
184
+ ;;
185
+ status)
186
+ cmd_status
187
+ ;;
188
+ logs)
189
+ cmd_logs
190
+ ;;
191
+ errors)
192
+ cmd_errors
193
+ ;;
194
+ help|--help|-h|"")
195
+ print_usage
196
+ ;;
197
+ *)
198
+ print_message "$RED" "Error: Unknown command '$1'"
199
+ echo ""
200
+ print_usage
201
+ exit 1
202
+ ;;
203
+ esac
@@ -0,0 +1,25 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2025/6/22 12:02
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
9
+
10
+ from .settings import settings
11
+ from .base import BaseConfig
12
+ from .db_relation import DatabaseConfig, DatabaseInstanceConfig
13
+ from .db_cache import RedisConfig
14
+ from .db_vector import VectorDBConfig
15
+ from .mq import MessageQueueConfig
16
+
17
+ __all__ = [
18
+ "settings",
19
+ "BaseConfig",
20
+ "DatabaseConfig",
21
+ "DatabaseInstanceConfig",
22
+ "RedisConfig",
23
+ "VectorDBConfig",
24
+ "MessageQueueConfig",
25
+ ]
infoman/config/base.py ADDED
@@ -0,0 +1,67 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2025/12/22 21:40
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
9
+
10
+ from typing import Literal
11
+ from pydantic_settings import BaseSettings
12
+ from pydantic import Field, field_validator
13
+
14
+
15
+ class BaseConfig(BaseSettings):
16
+ # ========== 环境 ==========
17
+ ENV: Literal["dev", "test", "prod"] = Field(default="dev")
18
+
19
+ # ========== 应用 ==========
20
+ APP_NAME: str = Field(default="InfoMan")
21
+ APP_BASE_URI: str = Field(default="/infoman")
22
+ APP_VERSION: str = Field(default="1.0.0")
23
+ APP_HOST: str = Field(default="0.0.0.0")
24
+ APP_PORT: int = Field(default=8000)
25
+ APP_DESCRIPTION: str = Field(default="Information System")
26
+
27
+ DEFAULT_LANGUAGE_IS_EN: bool = Field(default=True)
28
+
29
+ # ========== 服务器配置 ==========
30
+ APP_WORKERS: int = Field(default=2, description="工作进程数(Granian/Gunicorn)")
31
+ APP_THREADS: int = Field(default=1, description="每个 worker 的线程数(Granian)")
32
+
33
+ # ========== API 文档 ==========
34
+ DOCS_URL: str = Field(default="/doc")
35
+ APP_REDOC_URL: str = Field(default="/redoc")
36
+
37
+ # ========== CORS ==========
38
+ ALLOW_ORIGINS: list[str] = Field(default=["*"])
39
+ ALLOW_CREDENTIALS: bool = Field(default=False)
40
+ ALLOW_METHODS: list[str] = Field(default=["GET", "POST"])
41
+ ALLOW_HEADERS: list[str] = Field(default=["Content-Type", "Authorization", "X-Request-ID"])
42
+ MAX_AGE: int = Field(default=600)
43
+
44
+ # ========== Router配置 ==========
45
+ USE_DEFAULT_ROUTER: bool = Field(default=False)
46
+ USE_PROMETHEUS_ROUTER: bool = Field(default=False)
47
+ USE_STATIC: bool = Field(default=False)
48
+ STATIC_NAME: str = Field(default="static")
49
+ STATIC_DIR: str = Field(default="./app/static")
50
+ STATIC_URL: str = Field(default="/static")
51
+ USE_TEMPLATES: bool = Field(default=False)
52
+ TEMPLATE_DIR: str = Field(default="./app/template")
53
+
54
+ @property
55
+ def is_dev(self) -> bool:
56
+ return self.ENV == "dev"
57
+
58
+ @property
59
+ def is_test(self) -> bool:
60
+ return self.ENV == "test"
61
+
62
+ @property
63
+ def is_prod(self) -> bool:
64
+ return self.ENV == "pro"
65
+
66
+
67
+
@@ -0,0 +1,237 @@
1
+ # !/usr/bin/env python
2
+ # -*-coding:utf-8 -*-
3
+
4
+ """
5
+ # Time :2025/12/22 21:37
6
+ # Author :Maxwell
7
+ # Description:
8
+ """
9
+ from typing import Optional, Literal
10
+ from pydantic import Field, field_validator
11
+ from pydantic_settings import BaseSettings
12
+
13
+
14
+ class RedisConfig(BaseSettings):
15
+ """Redis/DragonflyDB 缓存配置"""
16
+
17
+ # ========== 基础配置 ==========
18
+ REDIS_ENABLED: bool = Field(
19
+ default=False,
20
+ description="是否启用缓存服务"
21
+ )
22
+
23
+ REDIS_BACKEND: Literal["redis", "dragonfly", "auto"] = Field(
24
+ default="auto",
25
+ description="缓存后端类型:redis/dragonfly/auto(自动检测)"
26
+ )
27
+
28
+ REDIS_HOST: Optional[str] = Field(
29
+ default=None,
30
+ description="缓存服务器主机地址"
31
+ )
32
+
33
+ REDIS_PORT: int = Field(
34
+ default=6379,
35
+ description="缓存服务器端口"
36
+ )
37
+
38
+ REDIS_DB: int = Field(
39
+ default=0,
40
+ ge=0,
41
+ le=15,
42
+ description="Redis 数据库编号(0-15)"
43
+ )
44
+
45
+ REDIS_PASSWORD: Optional[str] = Field(
46
+ default=None,
47
+ description="缓存服务器密码"
48
+ )
49
+
50
+ # ========== 连接池配置 ==========
51
+ REDIS_MAX_CONNECTIONS: int = Field(
52
+ default=30,
53
+ ge=1,
54
+ le=1000,
55
+ description="连接池最大连接数"
56
+ )
57
+
58
+ REDIS_SOCKET_TIMEOUT: int = Field(
59
+ default=4,
60
+ ge=1,
61
+ description="Socket 超时时间(秒)"
62
+ )
63
+
64
+ REDIS_SOCKET_CONNECT_TIMEOUT: int = Field(
65
+ default=2,
66
+ ge=1,
67
+ description="连接超时时间(秒)"
68
+ )
69
+
70
+ REDIS_HEALTH_CHECK_INTERVAL: int = Field(
71
+ default=30,
72
+ ge=0,
73
+ description="健康检查间隔(秒),0 表示禁用"
74
+ )
75
+
76
+ REDIS_RETRY_ON_TIMEOUT: bool = Field(
77
+ default=True,
78
+ description="超时时是否自动重试"
79
+ )
80
+
81
+ # ========== 缓存配置 ==========
82
+ REDIS_CACHE_PREFIX: str = Field(
83
+ default="infoman",
84
+ description="缓存 key 前缀"
85
+ )
86
+
87
+ REDIS_CACHE_EXPIRE: int = Field(
88
+ default=3600,
89
+ ge=0,
90
+ description="默认缓存过期时间(秒),0 表示永不过期"
91
+ )
92
+
93
+ REDIS_CACHE_VERSION: Optional[str] = Field(
94
+ default=None,
95
+ description="缓存版本号(用于缓存失效),留空则使用应用版本"
96
+ )
97
+
98
+ # ========== 编码配置 ==========
99
+ REDIS_ENCODING: str = Field(
100
+ default="utf-8",
101
+ description="编码格式"
102
+ )
103
+
104
+ REDIS_DECODE_RESPONSES: bool = Field(
105
+ default=False,
106
+ description="是否自动解码响应(True: 返回 str,False: 返回 bytes)"
107
+ )
108
+
109
+ # ========== 验证器 ==========
110
+
111
+ @field_validator("REDIS_BACKEND")
112
+ @classmethod
113
+ def validate_backend(cls, v: str) -> str:
114
+ """验证后端类型"""
115
+ allowed = ["redis", "dragonfly", "auto"]
116
+ if v not in allowed:
117
+ raise ValueError(f"REDIS_BACKEND 必须是 {allowed} 之一")
118
+ return v
119
+
120
+ @field_validator("REDIS_CACHE_PREFIX")
121
+ @classmethod
122
+ def validate_prefix(cls, v: str) -> str:
123
+ if not v or not v.strip():
124
+ raise ValueError("REDIS_CACHE_PREFIX 不能为空")
125
+ return v.strip()
126
+
127
+ @field_validator("REDIS_HOST")
128
+ @classmethod
129
+ def validate_host(cls, v: Optional[str]) -> Optional[str]:
130
+ """验证主机地址"""
131
+ if v:
132
+ v = v.strip()
133
+ if not v:
134
+ return None
135
+ return v
136
+
137
+ # ========== 计算属性 ==========
138
+
139
+ @property
140
+ def redis_configured(self) -> bool:
141
+ return self.REDIS_ENABLED and bool(self.REDIS_HOST)
142
+
143
+ @property
144
+ def is_redis(self) -> bool:
145
+ """是否使用 Redis"""
146
+ return self.REDIS_BACKEND == "redis"
147
+
148
+ @property
149
+ def is_dragonfly(self) -> bool:
150
+ """是否使用 DragonflyDB"""
151
+ return self.REDIS_BACKEND == "dragonfly"
152
+
153
+ @property
154
+ def is_auto(self) -> bool:
155
+ """是否自动检测"""
156
+ return self.REDIS_BACKEND == "auto"
157
+
158
+ @property
159
+ def connection_url(self) -> Optional[str]:
160
+ """
161
+ 获取连接 URL
162
+
163
+ Returns:
164
+ Redis 连接 URL,例如:redis://:password@localhost:6379/0
165
+ """
166
+ if not self.redis_configured:
167
+ return None
168
+
169
+ auth = f":{self.REDIS_PASSWORD}@" if self.REDIS_PASSWORD else ""
170
+ return f"redis://{auth}{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}"
171
+
172
+ def get_cache_key(self, key: str, version: Optional[str] = None) -> str:
173
+ """
174
+ 生成完整的缓存 key
175
+
176
+ Args:
177
+ key: 原始 key
178
+ version: 版本号,留空则使用配置的版本
179
+
180
+ Returns:
181
+ 完整的缓存 key,例如:infoman:v1.0.0:user:123
182
+ """
183
+ version = version or self.REDIS_CACHE_VERSION or "default"
184
+ return f"{self.REDIS_CACHE_PREFIX}:v{version}:{key}"
185
+
186
+ def to_dict(self) -> dict:
187
+ """
188
+ 转换为字典(隐藏敏感信息)
189
+
190
+ Returns:
191
+ 配置字典
192
+ """
193
+ return {
194
+ "enabled": self.REDIS_ENABLED,
195
+ "backend": self.REDIS_BACKEND,
196
+ "host": self.REDIS_HOST,
197
+ "port": self.REDIS_PORT,
198
+ "db": self.REDIS_DB,
199
+ "password": "***" if self.REDIS_PASSWORD else None,
200
+ "max_connections": self.REDIS_MAX_CONNECTIONS,
201
+ "cache_prefix": self.REDIS_CACHE_PREFIX,
202
+ "cache_expire": self.REDIS_CACHE_EXPIRE,
203
+ "configured": self.redis_configured,
204
+ }
205
+
206
+
207
+ def get_redis_config() -> RedisConfig:
208
+ return RedisConfig()
209
+
210
+
211
+ def print_redis_config():
212
+ config = get_redis_config()
213
+
214
+ print("=" * 60)
215
+ print("Redis/DragonflyDB 缓存配置")
216
+ print("=" * 60)
217
+
218
+ for key, value in config.to_dict().items():
219
+ print(f" {key:20s}: {value}")
220
+
221
+ print("=" * 60)
222
+ print(f" 连接 URL: {config.connection_url or '未配置'}")
223
+ print("=" * 60)
224
+
225
+
226
+ # ========== 使用示例 ==========
227
+
228
+ if __name__ == "__main__":
229
+ # 打印配置
230
+ print_redis_config()
231
+
232
+ # 测试缓存 key 生成
233
+ config = get_redis_config()
234
+
235
+ print("\n缓存 Key 示例:")
236
+ print(f" user:123 -> {config.get_cache_key('user:123')}")
237
+ print(f" session:abc -> {config.get_cache_key('session:abc', version='2.0.0')}")