Files
OpenFlare/docs/plan/of-options-migration.md
T
2026-06-22 22:23:49 +08:00

192 lines
9.5 KiB
Markdown
Raw 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.
# of_options 迁移到 w_system_configs 方案
## 背景
当前 OpenFlare 使用 `of_options` 表存储系统配置,维护了独立的 OptionMap 内存缓存和热重载机制。为了统一配置管理框架,需要将所有配置迁移到标准的 `w_system_configs` 表,复用现有的 SystemConfig 读取 API 和 Redis 缓存机制。
## 配置项分类
### 已存在于 w_system_configs,无需迁移
以下配置在新系统中已存在,不从 of_options 迁移:
- `PasswordLoginEnabled` → `password_login_enabled` (已存在)
- `CapLoginEnabled` → `cap_login_enabled` (已存在)
- `PasswordRegisterEnabled` → `password_register_enabled` (已存在)
- `EmailVerificationEnabled` → 映射到 `email_login_verification_enabled` (已存在)
- `ServerAddress` → `server_address` (已存在)
- `SMTPServer` → `smtp_host` (已存在,字段名不同)
- `SMTPPort` → `smtp_port` (已存在)
- `SMTPAccount` → `smtp_username` (已存在,字段名不同)
- `SMTPToken` → `smtp_password` (已存在,字段名不同)
### 旧系统冗余配置,直接删除
以下配置是旧系统遗留,当前系统不使用,不迁移:
- `SystemName` - 前端不再使用系统名称配置
- `Footer` - 前端不再使用页脚 HTML
- `HomePageLink` - 前端不再使用首页链接
- `About` - 前端不再使用关于信息
### 需要迁移的配置(全部 type=business)
**所有迁移的配置都设为 business 类型**。system 类型仅用于框架级配置(如 upload_allowed_extensions、disk_cache_max_size_mb 等)。
#### Agent 相关配置 (business, visibility=0)
| 原 Key (PascalCase) | 新 Key (snake_case) | 默认值 | 说明 |
|---------------------|---------------------|--------|------|
| AgentDiscoveryToken | agent_discovery_token | "" | Agent 发现令牌(敏感) |
| AgentHeartbeatInterval | agent_heartbeat_interval | 10000 | Agent 心跳间隔(毫秒) |
| AgentWebsocketUpgradeEnabled | agent_websocket_upgrade_enabled | true | Agent WebSocket 升级开关 |
| NodeOfflineThreshold | node_offline_threshold | 120000 | 节点离线阈值(毫秒) |
| AgentUpdateRepo | agent_update_repo | Rain-kl/OpenFlare | Agent 更新仓库 |
#### 系统功能配置 (business, visibility=0)
| 原 Key (PascalCase) | 新 Key (snake_case) | 默认值 | 说明 |
|---------------------|---------------------|--------|------|
| GeoIPProvider | geoip_provider | ipinfo | GeoIP 服务商 |
| DatabaseAutoCleanupEnabled | database_auto_cleanup_enabled | false | 数据库自动清理开关 |
| DatabaseAutoCleanupRetentionDays | database_auto_cleanup_retention_days | 30 | 数据库保留天数 |
#### UptimeKuma 集成配置 (business, visibility=0)
| 原 Key (PascalCase) | 新 Key (snake_case) | 默认值 | 说明 |
|---------------------|---------------------|--------|------|
| UptimeKumaEnabled | uptime_kuma_enabled | false | UptimeKuma 集成开关 |
| UptimeKumaUrl | uptime_kuma_url | "" | UptimeKuma URL |
| UptimeKumaUsername | uptime_kuma_username | "" | UptimeKuma 用户名 |
| UptimeKumaPassword | uptime_kuma_password | "" | UptimeKuma 密码(敏感) |
| UptimeKumaMonitorScope | uptime_kuma_monitor_scope | all | UptimeKuma 监控范围 |
| UptimeKumaSelectedSites | uptime_kuma_selected_sites | "" | UptimeKuma 选定站点 |
| UptimeKumaSyncInterval | uptime_kuma_sync_interval | 5 | UptimeKuma 同步间隔(分钟) |
| UptimeKumaInterval | uptime_kuma_interval | 60 | UptimeKuma 监控间隔(秒) |
| UptimeKumaRetry | uptime_kuma_retry | 0 | UptimeKuma 重试次数 |
| UptimeKumaRetryInterval | uptime_kuma_retry_interval | 60 | UptimeKuma 重试间隔(秒) |
| UptimeKumaTimeout | uptime_kuma_timeout | 48 | UptimeKuma 超时(秒) |
### OpenResty 配置 (type=business)
OpenResty 反向代理和缓存配置,全部为 business 类型,visibility=0:
| 原 Key (PascalCase) | 新 Key (snake_case) | 默认值 |
|---------------------|---------------------|--------|
| OpenRestyDefaultServerReturnStatus | openresty_default_server_return_status | 421 |
| OpenRestyWorkerProcesses | openresty_worker_processes | auto |
| OpenRestyWorkerConnections | openresty_worker_connections | 4096 |
| OpenRestyWorkerRlimitNofile | openresty_worker_rlimit_nofile | 65535 |
| OpenRestyEventsUse | openresty_events_use | epoll |
| OpenRestyEventsMultiAcceptEnabled | openresty_events_multi_accept_enabled | true |
| OpenRestyKeepaliveTimeout | openresty_keepalive_timeout | 20 |
| OpenRestyKeepaliveRequests | openresty_keepalive_requests | 1000 |
| OpenRestyClientHeaderTimeout | openresty_client_header_timeout | 15 |
| OpenRestyClientBodyTimeout | openresty_client_body_timeout | 15 |
| OpenRestyClientMaxBodySize | openresty_client_max_body_size | 64m |
| OpenRestyLargeClientHeaderBuffers | openresty_large_client_header_buffers | 4 16k |
| OpenRestySendTimeout | openresty_send_timeout | 30 |
| OpenRestyResolvers | openresty_resolvers | "" |
| OpenRestyProxyConnectTimeout | openresty_proxy_connect_timeout | 3 |
| OpenRestyProxySendTimeout | openresty_proxy_send_timeout | 60 |
| OpenRestyProxyReadTimeout | openresty_proxy_read_timeout | 60 |
| OpenRestyWebsocketEnabled | openresty_websocket_enabled | true |
| OpenRestyHTTP3Enabled | openresty_http3_enabled | true |
| OpenRestyProxyRequestBufferingEnabled | openresty_proxy_request_buffering_enabled | false |
| OpenRestyProxyBufferingEnabled | openresty_proxy_buffering_enabled | true |
| OpenRestyProxyBuffers | openresty_proxy_buffers | 16 16k |
| OpenRestyProxyBufferSize | openresty_proxy_buffer_size | 8k |
| OpenRestyProxyBusyBuffersSize | openresty_proxy_busy_buffers_size | 64k |
| OpenRestyGzipEnabled | openresty_gzip_enabled | true |
| OpenRestyGzipMinLength | openresty_gzip_min_length | 1024 |
| OpenRestyGzipCompLevel | openresty_gzip_comp_level | 5 |
| OpenRestyCacheEnabled | openresty_cache_enabled | false |
| OpenRestyCachePath | openresty_cache_path | "" |
| OpenRestyCacheLevels | openresty_cache_levels | 1:2 |
| OpenRestyCacheInactive | openresty_cache_inactive | 30m |
| OpenRestyCacheMaxSize | openresty_cache_max_size | 1g |
| OpenRestyCacheKeyTemplate | openresty_cache_key_template | $scheme$host$request_uri |
| OpenRestyCacheLockEnabled | openresty_cache_lock_enabled | true |
| OpenRestyCacheLockTimeout | openresty_cache_lock_timeout | 5s |
| OpenRestyCacheUseStale | openresty_cache_use_stale | error timeout updating http_500... |
| OpenRestyMainConfigTemplate | openresty_main_config_template | (长模板) |
**总计**:约 58 个配置需要迁移,全部为 business 类型。
## 迁移策略
### 1. 保持向后兼容
- 在迁移期间同时支持旧 API (`/api/v1/openflare/options`) 和新 API (`/api/v1/admin/system-configs`)
- 旧 API 内部委派到 SystemConfig 读写,不再直接操作 of_options 表
- 保留 `/api/v1/openflare/status` 接口,但从 SystemConfig 读取数据
### 2. 数据迁移顺序
1. 创建新的 ConfigKey 常量(已完成)
2. 创建 goose 迁移脚本,将 of_options 真正需要的配置复制到 w_system_configs(已完成)
3. 重构代码使用 repository.GetSystemConfigByKey / GetBoolByKey / GetIntByKey
4. 标记 of_options 表为 deprecated(保留一段时间用于回滚)
5. 后续版本完全删除 of_options 相关代码
### 3. 配置类型说明
**所有从 of_options 迁移的配置都设为 business 类型**:
- `type='business'`:业务配置,影响业务规则和功能行为
- `type='system'`:框架配置,仅用于框架级设置(如 upload_allowed_extensions、disk_cache_max_size_mb)
**不迁移的配置**:
- 已存在于 w_system_configs 的配置(如 password_login_enabled、smtp_host)
- 旧系统冗余配置(SystemName、Footer、HomePageLink、About)
### 4. 包级变量处理
原 `openflare_option.go` 中的包级变量(如 `SystemName`、`PasswordLoginEnabled`)将被移除。所有读取改为:
```go
// 旧方式(包级变量)
systemName := model.SystemName
enabled := model.PasswordLoginEnabled
// 新方式(repository 读取)
systemName, err := repository.GetSystemConfigByKey(ctx, model.ConfigKeySystemName)
enabled, err := repository.GetBoolByKey(ctx, model.ConfigKeyPasswordLoginEnabled)
```
注意:对于已存在的配置,使用对应的新 key:
```go
// 已存在的配置使用现有 key
enabled, err := repository.GetBoolByKey(ctx, model.ConfigKeyPasswordLoginEnabled) // 不是 ConfigKeySystemName
```
### 5. 热重载机制
- 移除 `InitOptionMap` 和 `OptionMapRWMutex`
- SystemConfig 已通过 Redis 缓存实现热重载,更新后自动失效
## 实现步骤
1. ✅ 分析配置项并设计迁移方案(本文档)
2. 在 `system_configs.go` 添加所有 ConfigKey 常量
3. 创建 goose 迁移脚本(PostgreSQL + SQLite)
4. 重构所有业务代码使用 SystemConfig API
5. 更新 option 模块 API 和测试
6. 清理 of_options 遗留代码并验证
## 风险与注意事项
1. **敏感配置处理**:包含 Token/Password/Secret 的配置不应暴露给前端(visibility=0)
2. **类型转换**:of_options 将数值存为字符串,需要在读取时正确转换
3. **默认值一致性**:确保 SQL 迁移中的默认值与代码中的默认值一致
4. **模板配置**:`OpenRestyMainConfigTemplate` 是长文本,需要正确处理
5. **测试覆盖**:所有使用 OptionMap 的测试需要更新为使用 SystemConfig
## 后续清理计划
迁移完成后,在下一个主版本(如 v2.0)中完全移除:
- `internal/model/openflare_option.go`
- `internal/model/openflare_option_apply.go`
- `of_options` 表及相关迁移文件
- `internal/apps/openflare/option` 模块(或重构为 SystemConfig 的代理)