Files
aiops/backend/pkg/database/database.go
T
Logan.Li b7166acda4 优化 local 模式兼容性与部署可靠性
- SQL 方言层:agent updated_at、dashboard 小时分桶、清理任务跨 SQLite/MySQL
- Cache Capabilities:redka 跳过 ZSet/PubSub,Agent 聚合改 DB 直读
- local 模式 redka 初始化失败 Fatal;/version 返回 features
- SQLite WAL + 连接池限制;K8s data 改 PVC 持久化
- run.sh:旧参数迁移、升级后 /version 校验
2026-06-26 13:28:31 +08:00

165 lines
5.5 KiB
Go
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.
package database
import (
"fmt"
"strings"
"time"
"ezops/config"
"ezops/model"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"github.com/glebarez/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
// New 创建数据库连接
func New(cfg config.DatabaseConfig) (*gorm.DB, error) {
var dialector gorm.Dialector
switch cfg.Driver {
case "mysql":
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True&loc=Local",
cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DBName, cfg.Charset)
dialector = mysql.Open(dsn)
case "postgres":
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
cfg.Host, cfg.Port, cfg.User, cfg.Password, cfg.DBName)
dialector = postgres.Open(dsn)
case "sqlite":
dsn := cfg.DBName
if !strings.Contains(dsn, "?") {
// WAL 提升并发读,busy_timeout 降低锁冲突 // Logan.Li
dsn += "?_pragma=journal_mode(WAL)&_pragma=busy_timeout(5000)"
}
dialector = sqlite.Open(dsn)
if cfg.MaxConn > 4 {
cfg.MaxConn = 4
}
if cfg.MaxIdle > 2 {
cfg.MaxIdle = 2
}
default:
return nil, fmt.Errorf("unsupported database driver: %s", cfg.Driver)
}
db, err := gorm.Open(dialector, &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
if err != nil {
return nil, err
}
// 设置连接池
sqlDB, err := db.DB()
if err != nil {
return nil, err
}
sqlDB.SetMaxOpenConns(cfg.MaxConn)
sqlDB.SetMaxIdleConns(cfg.MaxIdle)
sqlDB.SetConnMaxLifetime(time.Hour)
return db, nil
}
// AutoMigrate 自动迁移数据库表
// 逐表迁移:单张表的迁移错误(如索引名冲突)不会阻塞其他表,
// 避免 GORM + MySQL 8.0 的 "Can't DROP" 索引问题导致整个启动失败
func AutoMigrate(db *gorm.DB) error {
allModels := []interface{}{
&model.User{},
&model.Role{},
&model.Permission{},
&model.Server{},
&model.Cloud{},
&model.CloudAccount{},
&model.Region{},
&model.Domain{},
&model.KubernetesCluster{},
&model.KubernetesNode{},
&model.KubernetesPod{},
&model.KubernetesDeployment{},
&model.KubernetesService{},
&model.KubernetesIngress{},
&model.AlertRule{},
&model.AlertEvent{},
&model.NotifyChannel{},
&model.MetricData{},
&model.Pipeline{},
&model.PipelineRun{},
&model.AppRelease{},
&model.CronJob{},
&model.Script{},
&model.TaskExecution{},
&model.ApprovalTemplate{},
&model.ApprovalProcess{},
&model.ApprovalStep{},
&model.NavigationGroup{},
&model.NavigationLink{},
&model.AuditLog{},
&model.LDAPConfig{},
&model.ResourceModel{},
&model.CloudBilling{},
&model.BillingAlertRule{},
&model.AgentReport{},
&model.AgentTask{},
&model.AgentRule{},
&model.AgentAlert{},
&model.AnsiblePlaybook{},
&model.AnsibleJob{},
&model.AnsibleInventory{},
&model.LogSource{},
&model.LogEntry{},
&model.TopologyLayout{}, // 拓扑布局保存 // Logan.Li
&model.TerminalSession{}, // 终端会话录制(终端审计) // Logan.Li
&model.LLMConfig{}, // 大语言模型配置(AI 智能助手) // Logan.Li
&model.ChatHistory{}, // 对话历史记录(按用户隔离) // Logan.Li
&model.MetricsAggregate{}, // 指标时序聚合(Redis → MySQL)// Logan.Li
&model.MonitorTarget{}, // 监控目标(主机/中间件/设备/站点) // Logan.Li
&model.MonitorMetric{}, // 监控指标定义 // Logan.Li
&model.MetricValue{}, // 指标当前值 // Logan.Li
&model.MetricHistory{}, // 指标历史时序 // Logan.Li
&model.HostGroup{}, // 主机组 // Logan.Li
&model.SNMPDevice{}, // SNMP设备 // Logan.Li
&model.SNMPTemplate{}, // SNMP模板 // Logan.Li
&model.SiteTask{}, // 站点拨测任务 // Logan.Li
&model.SiteResult{}, // 拨测结果 // Logan.Li
&model.SiteAlert{}, // 拨测告警 // Logan.Li
&model.PrometheusDataSource{}, // Prometheus 数据源配置 // Logan.Li
&model.ZabbixDataSource{}, // Zabbix 数据源配置 // Logan.Li
&model.Credential{}, // 凭据管理(SSH密钥/API Token) // Logan.Li
&model.PipelineRepo{}, // Git 仓库认证 // Logan.Li
&model.PipelineRegistry{}, // 镜像仓库认证 // Logan.Li
&model.DeployEnvironment{}, // 发布环境分组 // Logan.Li
&model.DeployPipelineMember{}, // 流水线成员 // Logan.Li
&model.DeployUserGroup{}, // 用户组 // Logan.Li
&model.DeployUserGroupMember{}, // 用户组成员 // Logan.Li
&model.ItemRole{}, // Jenkins-style Item Role (regex pipeline matching) // Logan.Li
&model.UserItemRole{}, // User ↔ ItemRole association // Logan.Li
&model.DeployTool{}, // 工具配置(懒加载/预装/禁用) // Logan.Li
&model.AlertCondition{}, // 告警条件 // Logan.Li
&model.AlertNotifyTemplate{}, // 告警通知模板 // Logan.Li
&model.AlertUpgrade{}, // 告警升级策略 // Logan.Li
&model.AlertUpgradeRecord{}, // 告警升级记录 // Logan.Li
&model.AlertSilence{}, // 告警静默 // Logan.Li
&model.HealthProbe{}, // 健康探针配置 // Logan.Li
&model.ApprovalWorkflow{}, // 审批流程定义 // Logan.Li
&model.ApprovalWorkflowStep{}, // 审批流程步骤 // Logan.Li
}
var lastErr error
for _, m := range allModels {
if err := db.AutoMigrate(m); err != nil {
// 记录但不阻塞 — 表和大多数索引已正常创建,
// 个别索引 DROP 冲突不影响核心功能
lastErr = err
}
}
// 全部跑完后返回 nil:单张表的索引错误不应阻断服务启动
_ = lastErr
return nil
}