fix: 消除游戏下拉重复请求并优化申请范围查询
This commit is contained in:
@@ -19,10 +19,18 @@ func approvedGamesAvailable(db *gorm.DB) (bool, error) {
|
||||
// 用平台和 ID 配对,避免同号游戏或其他商务的申请扩大可选范围。
|
||||
func approvedGamesQuery(db *gorm.DB, viewer business.UserScope, sources []string) *gorm.DB {
|
||||
promotes := ledgerBasePromotes(db, business.LedgerScope{Viewer: viewer, IncludeSub: true, Unrestricted: viewer.All}, business.LedgerFilter{Sources: sources}, "approved_p").Select("approved_p.source_db,approved_p.id")
|
||||
applications := db.Table("tab_promote_apply a").Select("a.source_db,a.game_id").Where("a.status=1").Where("(a.source_db,a.promote_id) IN (?)", promotes)
|
||||
q := db.Table("tab_game g").Where("(g.source_db,g.id) IN (?)", applications)
|
||||
// 逐个游戏检查有效申请,命中即停止;非相关 IN 在 MySQL 5.7 会先
|
||||
// 物化整张百万级申请表,即使下拉只需要前 50 项也要扫描全部申请。
|
||||
applications := db.Table("tab_promote_apply a").Select("1").Where("a.source_db=g.source_db AND a.game_id=g.id AND a.status=1").Where("(a.source_db,a.promote_id) IN (?)", promotes)
|
||||
q := db.Table("tab_game g").Where("EXISTS (?)", applications)
|
||||
if len(sources) > 0 {
|
||||
q = q.Where("g.source_db IN ?", sources)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func migrateApprovedGameIndexes(db *gorm.DB) error {
|
||||
return migrateQueryIndexes(db, []businessQueryIndex{
|
||||
{"tab_promote_apply", "idx_sw_apply_game_scope", []string{"game_id", "source_db", "status", "promote_id"}},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
func Migrations() []migration.Step {
|
||||
return []migration.Step{{ID: "202611040014_business_report_build_indexes", Migrate: migrateReportBuildQueryIndexes}, {ID: "202611040013_business_query_indexes", Migrate: migrateBusinessQueryIndexes}, {ID: "202611040012_business_server_report_index", Migrate: migrateServerReportIndex}, {ID: "202611040011_business_registration_index", Migrate: migrateRegistrationIndex}, {ID: "202611040010_business_alert_trigger_locks", Migrate: func(db *gorm.DB) error { return migration.CreateMissingTables(db, &alertTriggerLockPO{}) }}, {ID: "202611040009_business_menu_icons", Migrate: migrateBusinessMenuIcons}, {ID: "202611040008_business_report_build_locks", Migrate: func(db *gorm.DB) error { return migration.CreateMissingTables(db, &reportBuildLockPO{}) }}, {ID: "202611030007_business_alert_attachments", Migrate: migrateAlertAttachments}, {ID: "202611030006_business_alert_schema", Migrate: migrateAlertSchema}, {ID: "202611030005_business_password_reset", Migrate: func(db *gorm.DB) error {
|
||||
return []migration.Step{{ID: "202611040015_business_approved_game_index", Migrate: migrateApprovedGameIndexes}, {ID: "202611040014_business_report_build_indexes", Migrate: migrateReportBuildQueryIndexes}, {ID: "202611040013_business_query_indexes", Migrate: migrateBusinessQueryIndexes}, {ID: "202611040012_business_server_report_index", Migrate: migrateServerReportIndex}, {ID: "202611040011_business_registration_index", Migrate: migrateRegistrationIndex}, {ID: "202611040010_business_alert_trigger_locks", Migrate: func(db *gorm.DB) error { return migration.CreateMissingTables(db, &alertTriggerLockPO{}) }}, {ID: "202611040009_business_menu_icons", Migrate: migrateBusinessMenuIcons}, {ID: "202611040008_business_report_build_locks", Migrate: func(db *gorm.DB) error { return migration.CreateMissingTables(db, &reportBuildLockPO{}) }}, {ID: "202611030007_business_alert_attachments", Migrate: migrateAlertAttachments}, {ID: "202611030006_business_alert_schema", Migrate: migrateAlertSchema}, {ID: "202611030005_business_password_reset", Migrate: func(db *gorm.DB) error {
|
||||
return migration.CreateMissingTables(db, &resetCodePO{}, &resetTokenPO{})
|
||||
}}, {ID: "202611030004_business_binding_locks", Migrate: func(db *gorm.DB) error {
|
||||
return migration.CreateMissingTables(db, &bindingLockPO{})
|
||||
|
||||
@@ -1,12 +1,49 @@
|
||||
package business
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"kra/internal/biz/business"
|
||||
)
|
||||
|
||||
func TestMySQLApprovedGameIndexSupportsExistenceLookup(t *testing.T) {
|
||||
db := openRehearsalMySQL(t)
|
||||
for _, sql := range []string{
|
||||
"CREATE TABLE tab_game(id INT,source_db VARCHAR(10),game_name VARCHAR(64),PRIMARY KEY(id,source_db),KEY(game_name)) ENGINE=InnoDB",
|
||||
"CREATE TABLE tab_promote(id INT,source_db VARCHAR(10),PRIMARY KEY(id,source_db)) ENGINE=InnoDB",
|
||||
"CREATE TABLE tab_promote_apply(id INT PRIMARY KEY,source_db VARCHAR(10),game_id INT,promote_id INT,status INT,payload VARCHAR(500)) ENGINE=InnoDB",
|
||||
"INSERT INTO tab_game VALUES(1,'lx','游戏甲'),(1,'hw','无申请同号游戏')",
|
||||
"INSERT INTO tab_promote VALUES(100,'lx')",
|
||||
"INSERT INTO tab_promote_apply VALUES(1,'lx',1,100,1,'keep'),(2,'lx',1,100,0,'pending')",
|
||||
} {
|
||||
if err := db.Exec(sql).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for attempt := 0; attempt < 2; attempt++ {
|
||||
if err := migrateApprovedGameIndexes(db); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
var columns []string
|
||||
if err := db.Raw("SELECT column_name FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='tab_promote_apply' AND index_name='idx_sw_apply_game_scope' ORDER BY seq_in_index").Scan(&columns).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if strings.Join(columns, ",") != "game_id,source_db,status,promote_id" {
|
||||
t.Fatal("申请查询需要覆盖完整游戏、平台、状态和渠道条件")
|
||||
}
|
||||
rows, err := NewLedgerRepo(testData{db}).Games(context.Background(), business.UserScope{All: true}, nil, "", 50)
|
||||
if err != nil || len(rows) != 1 || rows[0].SourceDB != "lx" {
|
||||
t.Fatalf("索引不能改变游戏可见范围: %+v %v", rows, err)
|
||||
}
|
||||
var payload string
|
||||
if err := db.Raw("SELECT payload FROM tab_promote_apply WHERE id=1").Scan(&payload).Error; err != nil || payload != "keep" {
|
||||
t.Fatal("索引迁移不能修改申请数据")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMySQLBusinessQueryIndexesAreAdditiveAndIdempotent(t *testing.T) {
|
||||
db := openRehearsalMySQL(t)
|
||||
definitions := map[string]string{
|
||||
|
||||
Reference in New Issue
Block a user