fix(smoke): 修复首页 AI 建议降级与节点索引
This commit is contained in:
@@ -98,6 +98,10 @@ func AutoMigrate(models ...interface{}) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := repairSmokeAINextSmokeIndexes(DB); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type mysqlIndexColumn struct {
|
||||
KeyName string `gorm:"column:Key_name"`
|
||||
SeqInIndex int `gorm:"column:Seq_in_index"`
|
||||
ColumnName string `gorm:"column:Column_name"`
|
||||
}
|
||||
|
||||
func repairSmokeAINextSmokeIndexes(db *gorm.DB) error {
|
||||
if db == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
tableName = "fa_smoke_ai_next_smoke"
|
||||
indexName = "uniq_smoke_ai_next_node"
|
||||
)
|
||||
|
||||
var rows []mysqlIndexColumn
|
||||
if err := db.Raw(fmt.Sprintf("SHOW INDEX FROM `%s` WHERE Key_name = ?", tableName), indexName).Scan(&rows).Error; err != nil {
|
||||
return fmt.Errorf("inspect %s: %w", indexName, err)
|
||||
}
|
||||
|
||||
expected := []string{"ai_advice_id", "node_type", "node_at"}
|
||||
actual := make([]string, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
actual = append(actual, row.ColumnName)
|
||||
}
|
||||
|
||||
if slices.Equal(actual, expected) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(rows) > 0 {
|
||||
if err := db.Exec(fmt.Sprintf("ALTER TABLE `%s` DROP INDEX `%s`", tableName, indexName)).Error; err != nil {
|
||||
return fmt.Errorf("drop %s: %w", indexName, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.Exec(
|
||||
fmt.Sprintf(
|
||||
"ALTER TABLE `%s` ADD UNIQUE KEY `%s` (`ai_advice_id`,`node_type`,`node_at`)",
|
||||
tableName,
|
||||
indexName,
|
||||
),
|
||||
).Error; err != nil {
|
||||
return fmt.Errorf("create %s: %w", indexName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
func newMockDB(t *testing.T) (*gorm.DB, sqlmock.Sqlmock, func()) {
|
||||
t.Helper()
|
||||
|
||||
sqlDB, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("sqlmock.New: %v", err)
|
||||
}
|
||||
|
||||
gdb, err := gorm.Open(mysql.New(mysql.Config{
|
||||
Conn: sqlDB,
|
||||
SkipInitializeWithVersion: true,
|
||||
}), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Silent),
|
||||
})
|
||||
if err != nil {
|
||||
_ = sqlDB.Close()
|
||||
t.Fatalf("gorm.Open: %v", err)
|
||||
}
|
||||
|
||||
return gdb, mock, func() { _ = sqlDB.Close() }
|
||||
}
|
||||
|
||||
func TestRepairSmokeAINextSmokeIndexesRecreatesBrokenIndex(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, mock, cleanup := newMockDB(t)
|
||||
defer cleanup()
|
||||
|
||||
mock.ExpectQuery("SHOW INDEX FROM `fa_smoke_ai_next_smoke` WHERE Key_name = \\?").
|
||||
WithArgs("uniq_smoke_ai_next_node").
|
||||
WillReturnRows(
|
||||
sqlmock.NewRows([]string{"Key_name", "Seq_in_index", "Column_name"}).
|
||||
AddRow("uniq_smoke_ai_next_node", 1, "node_type").
|
||||
AddRow("uniq_smoke_ai_next_node", 2, "node_at"),
|
||||
)
|
||||
mock.ExpectExec("ALTER TABLE `fa_smoke_ai_next_smoke` DROP INDEX `uniq_smoke_ai_next_node`").
|
||||
WillReturnResult(sqlmock.NewResult(0, 0))
|
||||
mock.ExpectExec("ALTER TABLE `fa_smoke_ai_next_smoke` ADD UNIQUE KEY `uniq_smoke_ai_next_node` \\(`ai_advice_id`,`node_type`,`node_at`\\)").
|
||||
WillReturnResult(sqlmock.NewResult(0, 0))
|
||||
|
||||
if err := repairSmokeAINextSmokeIndexes(db); err != nil {
|
||||
t.Fatalf("repairSmokeAINextSmokeIndexes: %v", err)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("unmet expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepairSmokeAINextSmokeIndexesKeepsCorrectIndex(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, mock, cleanup := newMockDB(t)
|
||||
defer cleanup()
|
||||
|
||||
mock.ExpectQuery("SHOW INDEX FROM `fa_smoke_ai_next_smoke` WHERE Key_name = \\?").
|
||||
WithArgs("uniq_smoke_ai_next_node").
|
||||
WillReturnRows(
|
||||
sqlmock.NewRows([]string{"Key_name", "Seq_in_index", "Column_name"}).
|
||||
AddRow("uniq_smoke_ai_next_node", 1, "ai_advice_id").
|
||||
AddRow("uniq_smoke_ai_next_node", 2, "node_type").
|
||||
AddRow("uniq_smoke_ai_next_node", 3, "node_at"),
|
||||
)
|
||||
|
||||
if err := repairSmokeAINextSmokeIndexes(db); err != nil {
|
||||
t.Fatalf("repairSmokeAINextSmokeIndexes: %v", err)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("unmet expectations: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user