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,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')}")
|