fix(deploy): 全新部署链路健壮性(0004 幂等 + 迁移前置 + 空库守卫)
AIOps CI / Backend (test, vet, build) (push) Canceled after 0s
AIOps CI / Agent (test, vet, build) (push) Canceled after 0s
AIOps CI / Frontend (typecheck, lint, build) (push) Canceled after 0s
AIOps CI / API integration (SQLite + redka) (push) Canceled after 0s

- 0004_metric_aggregate_unique 改为幂等:新库基线已由模型 uniqueIndex 建出
  uniq_metric_agg,再次 CREATE 会以 1061 重复键名中断 migrate up,
  导致 0005_agent_settings 建不出来(全新部署实测复现)
- 新增 database.IndexExists:跨 SQLite/MySQL/PostgreSQL 判断索引是否存在
- 新增 database.EnsureSchemaInitialized:服务启动遇到空库时明确失败并给出
  执行 aiops migrate up 的指引,避免「服务起来了但页面全是空数据」
- run.sh docker up/upgrade/update 先跑一次 aiops migrate up 再启动服务

// Logan.Li
This commit is contained in:
Logan.Li committed 2026-09-14 09:02:42 +00:00
1 parent 7a96381dc7
commit f3a4fb569f
5 files changed
+57

No files matched your search

+22
View File
@@ -61,3 +61,25 @@ func CleanupSNMPMetricsSQL(driver string, retentionDays int) string {
)
}
}
// IndexExists 判断某表上是否已存在指定名称的索引(跨 SQLite / MySQL / PostgreSQL)。
// 供版本化迁移做幂等判断:新库基线已由模型(uniqueIndex 标签)建出同名索引时,
// 迁移不应再建一次,否则 MySQL 会以 1061 重复键名中断整个 migrate up。 // Logan.Li
func IndexExists(db *gorm.DB, table string, index string) (bool, error) {
var (
query string
count int64
)
switch DriverName(db) {
case "sqlite":
query = "SELECT COUNT(*) FROM sqlite_master WHERE type = 'index' AND tbl_name = ? AND name = ?"
case "postgres":
query = "SELECT COUNT(*) FROM pg_indexes WHERE schemaname = current_schema() AND tablename = ? AND indexname = ?"
default:
query = "SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = ? AND index_name = ?"
}
if err := db.Raw(query, table, index).Scan(&count).Error; err != nil {
return false, fmt.Errorf("检查索引 %s.%s 是否存在失败: %w", table, index, err)
}
return count > 0, nil
}