mmap/docs/SETTINGS_SYSTEM.md
Tsuki d4448c6129
Some checks are pending
Docker Build and Push / build (push) Waiting to run
sync: add settings
2025-08-11 00:05:52 +08:00

448 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Settings 配置管理系统
## 概述
Settings系统是一个灵活的、可扩展的配置管理系统用于管理网络后台的各种配置项。它使用PostgreSQL数据库存储配置支持多种数据类型并提供缓存、验证、历史记录等功能。
## 特性
- **灵活的数据类型支持**: 支持string、number、boolean、json等类型
- **分类管理**: 按功能模块分类组织配置项
- **权限控制**: 区分系统配置和用户配置,支持只读配置
- **缓存机制**: 内置缓存,提高配置访问性能
- **历史记录**: 自动记录配置变更历史,支持审计
- **类型安全**: 提供类型安全的配置访问API
- **批量操作**: 支持批量更新和导入导出
- **GraphQL接口**: 完整的GraphQL API支持
## 数据库结构
### settings表
```sql
CREATE TABLE settings (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
key VARCHAR(255) NOT NULL UNIQUE,
value TEXT,
value_type VARCHAR(50) NOT NULL DEFAULT 'string',
description TEXT,
category VARCHAR(100) DEFAULT 'general',
is_encrypted BOOLEAN DEFAULT FALSE,
is_system BOOLEAN DEFAULT FALSE,
is_editable BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_by UUID,
updated_by UUID
);
```
### settings_history表
```sql
CREATE TABLE settings_history (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
setting_id UUID NOT NULL REFERENCES settings(id) ON DELETE CASCADE,
old_value TEXT,
new_value TEXT,
changed_by UUID,
change_reason TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
```
## 核心组件
### 1. SettingsService
基础的配置服务提供CRUD操作
```rust
use crate::services::settings_service::SettingsService;
let settings_service = SettingsService::new(pool);
// 创建配置
let setting = settings_service.create_setting(create_setting, user_id).await?;
// 获取配置
let setting = settings_service.get_setting_by_key("app.name").await?;
// 更新配置
let updated = settings_service.update_setting(id, update_setting, user_id).await?;
// 删除配置
let deleted = settings_service.delete_setting(id).await?;
```
### 2. SettingsManager
高级配置管理器,提供缓存和类型安全的访问:
```rust
use crate::services::settings_manager::{SettingsManager, keys};
let settings_manager = SettingsManager::new(settings_service);
// 类型安全的配置访问
let app_name = settings_manager.get_string_or(keys::APP_NAME, "Default App").await?;
let max_connections = settings_manager.get_int_or(keys::DB_MAX_CONNECTIONS, 10).await?;
let debug_mode = settings_manager.get_bool_or(keys::APP_DEBUG, false).await?;
// 动态更新配置
settings_manager.set_value(keys::DB_MAX_CONNECTIONS, &20).await?;
// 批量更新
let mut updates = HashMap::new();
updates.insert(keys::KAFKA_MAX_RETRIES.to_string(), Value::Number(5));
settings_manager.set_values(updates).await?;
```
### 3. SettingsValidator
配置验证器,确保配置的完整性和正确性:
```rust
use crate::services::settings_manager::SettingsValidator;
// 验证必需配置
let missing = SettingsValidator::validate_required_settings(&manager).await?;
// 验证配置类型
let type_errors = SettingsValidator::validate_setting_types(&manager).await?;
```
## 预定义配置键
系统预定义了一些常用的配置键:
```rust
pub mod keys {
// 应用配置
pub const APP_NAME: &str = "app.name";
pub const APP_VERSION: &str = "app.version";
pub const APP_DEBUG: &str = "app.debug";
pub const APP_TIMEZONE: &str = "app.timezone";
// 数据库配置
pub const DB_MAX_CONNECTIONS: &str = "database.max_connections";
pub const DB_CONNECTION_TIMEOUT: &str = "database.connection_timeout";
// Kafka配置
pub const KAFKA_MAX_RETRIES: &str = "kafka.max_retries";
pub const KAFKA_RETRY_DELAY: &str = "kafka.retry_delay";
// 安全配置
pub const SECURITY_SESSION_TIMEOUT: &str = "security.session_timeout";
pub const SECURITY_MAX_LOGIN_ATTEMPTS: &str = "security.max_login_attempts";
// 日志配置
pub const LOGGING_LEVEL: &str = "logging.level";
pub const LOGGING_MAX_FILES: &str = "logging.max_files";
// 缓存配置
pub const CACHE_TTL: &str = "cache.ttl";
pub const CACHE_MAX_SIZE: &str = "cache.max_size";
}
```
## GraphQL API
### 查询
```graphql
# 获取所有配置
query {
settings {
id
key
value
valueType
description
category
isSystem
isEditable
createdAt
updatedAt
}
}
# 按分类过滤配置
query {
settings(filter: { category: "app" }) {
key
value
description
}
}
# 获取配置统计
query {
settingsStats {
categories
stats
}
}
# 获取配置历史
query {
settingHistory(settingId: "uuid") {
oldValue
newValue
changedBy
createdAt
}
}
```
### 变更
```graphql
# 创建配置
mutation {
createSetting(input: {
key: "custom.setting"
value: "custom_value"
valueType: "string"
description: "Custom setting"
category: "custom"
}) {
id
key
value
}
}
# 更新配置
mutation {
updateSetting(
id: "uuid"
input: { value: "new_value" }
) {
key
value
updatedAt
}
}
# 批量更新
mutation {
batchUpdateSettings(input: {
updates: [
{ key: "app.name", value: "New App Name" }
{ key: "app.debug", value: true }
]
}) {
key
value
}
}
# 删除配置
mutation {
deleteSetting(id: "uuid")
}
```
## 使用示例
### 基本使用
```rust
use crate::services::settings_manager::{SettingsManager, keys};
async fn configure_app(settings_manager: &SettingsManager) -> Result<(), Box<dyn std::error::Error>> {
// 获取应用配置
let app_name = settings_manager.get_string_or(keys::APP_NAME, "Default App").await?;
let debug_mode = settings_manager.get_bool_or(keys::APP_DEBUG, false).await?;
// 根据配置调整应用行为
if debug_mode {
println!("调试模式已启用");
// 设置更详细的日志级别
}
println!("应用名称: {}", app_name);
Ok(())
}
```
### 动态配置更新
```rust
async fn dynamic_config_update(settings_manager: &SettingsManager) -> Result<(), Box<dyn std::error::Error>> {
// 监听配置变化
loop {
let max_connections = settings_manager.get_int_or(keys::DB_MAX_CONNECTIONS, 10).await?;
let connection_timeout = settings_manager.get_int_or(keys::DB_CONNECTION_TIMEOUT, 30).await?;
// 根据配置调整数据库连接池
adjust_database_pool(max_connections, connection_timeout).await?;
// 等待一段时间后再次检查
tokio::time::sleep(tokio::time::Duration::from_secs(60)).await;
}
}
```
### 配置迁移
```rust
async fn migrate_old_configs(settings_service: &SettingsService) -> Result<(), Box<dyn std::error::Error>> {
let old_configs = vec![
("old.setting.1", "value1", "string"),
("old.setting.2", "100", "number"),
];
for (key, value, value_type) in old_configs {
let create_setting = CreateSetting {
key: key.to_string(),
value: Some(value.to_string()),
value_type: value_type.to_string(),
description: Some("Migrated from old system".to_string()),
category: "migrated".to_string(),
is_encrypted: Some(false),
is_system: Some(false),
is_editable: Some(true),
};
settings_service.create_setting(create_setting, uuid::Uuid::nil()).await?;
}
Ok(())
}
```
## 最佳实践
### 1. 配置命名规范
- 使用点分隔的层次结构:`module.submodule.setting_name`
- 使用小写字母和下划线
- 保持命名的一致性和可读性
### 2. 配置分类
- 按功能模块分类:`app`、`database`、`kafka`、`security`等
- 使用`general`分类存放通用配置
- 为自定义配置使用专门的分类名
### 3. 配置类型选择
- `string`: 文本配置,如应用名称、文件路径等
- `number`: 数值配置,如超时时间、连接数等
- `boolean`: 开关配置,如调试模式、功能开关等
- `json`: 复杂配置如API配置、映射关系等
### 4. 安全考虑
- 敏感配置设置`is_encrypted = true`
- 系统关键配置设置`is_system = true`
- 只读配置设置`is_editable = false`
### 5. 性能优化
- 合理使用缓存,避免频繁数据库查询
- 批量操作减少数据库往返
- 定期清理历史记录表
## 扩展性
### 添加新的配置类型
```rust
// 在Settings模型中添加新的类型支持
impl Setting {
pub fn get_custom_type(&self) -> Result<CustomType, String> {
if self.value_type == "custom" {
// 自定义类型解析逻辑
CustomType::from_str(&self.value.unwrap_or_default())
.map_err(|e| e.to_string())
} else {
Err("Setting is not a custom type".to_string())
}
}
}
```
### 添加新的配置分类
```rust
// 在keys模块中添加新的分类常量
pub mod keys {
// 现有分类...
// 新功能分类
pub const NEW_FEATURE_ENABLED: &str = "new_feature.enabled";
pub const NEW_FEATURE_TIMEOUT: &str = "new_feature.timeout";
}
```
### 自定义验证规则
```rust
impl SettingsValidator {
pub async fn validate_custom_rules(manager: &SettingsManager) -> Result<Vec<String>> {
let mut errors = Vec::new();
// 自定义验证逻辑
let feature_enabled = manager.get_bool_or(keys::NEW_FEATURE_ENABLED, false).await?;
let feature_timeout = manager.get_int_or(keys::NEW_FEATURE_TIMEOUT, 30).await?;
if feature_enabled && feature_timeout < 10 {
errors.push("Feature timeout must be at least 10 seconds when enabled".to_string());
}
Ok(errors)
}
}
```
## 故障排除
### 常见问题
1. **配置不生效**
- 检查缓存是否过期
- 验证配置项是否存在
- 确认配置项类型是否正确
2. **性能问题**
- 检查缓存设置
- 优化数据库查询
- 减少不必要的配置访问
3. **权限问题**
- 确认用户角色
- 检查配置项是否可编辑
- 验证系统配置保护
### 调试技巧
```rust
// 启用详细日志
if settings_manager.get_bool_or(keys::APP_DEBUG, false).await? {
println!("当前配置状态:");
let all_settings = settings_manager.get_all_settings().await?;
for setting in all_settings {
println!(" {}: {} ({})", setting.key, setting.value.unwrap_or_default(), setting.value_type);
}
}
// 强制刷新缓存
settings_manager.force_refresh_cache().await?;
```
## 总结
Settings系统提供了一个强大而灵活的配置管理解决方案支持
- 多种数据类型的配置存储
- 分类管理和权限控制
- 缓存和性能优化
- 完整的GraphQL API
- 配置历史记录和审计
- 类型安全的配置访问
- 易于扩展和维护
通过合理使用这个系统,可以大大简化应用程序的配置管理,提高系统的可维护性和灵活性。