fix: 修复商务汇总任务超时并验证计划启用
This commit is contained in:
@@ -2,6 +2,7 @@ package business
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -111,12 +112,17 @@ func (r *reportBuildRepo) Rebuild(ctx context.Context, kind business.ReportBuild
|
||||
func loadReportInput(db *gorm.DB, kind business.ReportBuildKind, day time.Time) (*business.ReportInput, error) {
|
||||
input := &business.ReportInput{Users: map[business.ReportUserKey]business.ReportUser{}, Games: map[business.AnalyticsKey]string{}}
|
||||
begin, end := day.Unix(), day.AddDate(0, 0, 1).Unix()-1
|
||||
userIDs, gameIDs := map[int64]bool{}, map[int64]bool{}
|
||||
userKeys := map[business.ReportUserKey]bool{}
|
||||
unknownUserIDs, gameIDs := map[int64]bool{}, map[int64]bool{}
|
||||
collect := func(rows []reportEventPO, target *[]business.ReportEvent) {
|
||||
for _, po := range rows {
|
||||
*target = append(*target, toReportEvent(po))
|
||||
if po.UserID != nil {
|
||||
userIDs[*po.UserID] = true
|
||||
if strings.TrimSpace(po.SourceDB) == "" {
|
||||
unknownUserIDs[*po.UserID] = true
|
||||
} else {
|
||||
userKeys[business.ReportUserKey{SourceDB: po.SourceDB, ID: *po.UserID}] = true
|
||||
}
|
||||
}
|
||||
if po.GameID != nil {
|
||||
gameIDs[*po.GameID] = true
|
||||
@@ -166,29 +172,16 @@ func loadReportInput(db *gorm.DB, kind business.ReportBuildKind, day time.Time)
|
||||
return nil, business.ErrStorage
|
||||
}
|
||||
collect(pays, &input.Payments)
|
||||
ids := make([]int64, 0, len(userIDs))
|
||||
for id := range userIDs {
|
||||
ids = append(ids, id)
|
||||
var err error
|
||||
input.Users, err = loadReportUsers(db, userKeys, unknownUserIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for start := 0; start < len(ids); start += 500 {
|
||||
var users []struct {
|
||||
ID int64
|
||||
SourceDB string `gorm:"column:source_db"`
|
||||
Puid, PromoteID *int64
|
||||
IDCard string `gorm:"column:idcard"`
|
||||
}
|
||||
if err := db.Table("tab_user").Select("id,source_db,puid,promote_id,idcard").Where("id IN ?", ids[start:min(start+500, len(ids))]).Scan(&users).Error; err != nil {
|
||||
return nil, business.ErrStorage
|
||||
}
|
||||
for _, po := range users {
|
||||
key := business.ReportUserKey{SourceDB: po.SourceDB, ID: po.ID}
|
||||
input.Users[key] = business.ReportUser{ReportUserKey: key, ParentID: po.Puid, PromoteID: po.PromoteID, IDCard: po.IDCard}
|
||||
}
|
||||
}
|
||||
ids = make([]int64, 0, len(gameIDs))
|
||||
ids := make([]int64, 0, len(gameIDs))
|
||||
for id := range gameIDs {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
|
||||
for start := 0; start < len(ids); start += 500 {
|
||||
var games []struct {
|
||||
ID int64
|
||||
@@ -207,6 +200,61 @@ func loadReportInput(db *gorm.DB, kind business.ReportBuildKind, day time.Time)
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// 已知平台的事件按完整主键读用户,避免将其他平台同号的大行一起回表。
|
||||
// 只有缺平台的事件读取全部同号用户,以保留旧逻辑的唯一主账号归属判断。
|
||||
func loadReportUsers(db *gorm.DB, known map[business.ReportUserKey]bool, unknown map[int64]bool) (map[business.ReportUserKey]business.ReportUser, error) {
|
||||
result := map[business.ReportUserKey]business.ReportUser{}
|
||||
read := func(query *gorm.DB) error {
|
||||
var users []struct {
|
||||
ID int64
|
||||
SourceDB string `gorm:"column:source_db"`
|
||||
Puid, PromoteID *int64
|
||||
IDCard string `gorm:"column:idcard"`
|
||||
}
|
||||
if err := query.Select("id,source_db,puid,promote_id,idcard").Scan(&users).Error; err != nil {
|
||||
return business.ErrStorage
|
||||
}
|
||||
for _, po := range users {
|
||||
key := business.ReportUserKey{SourceDB: po.SourceDB, ID: po.ID}
|
||||
result[key] = business.ReportUser{ReportUserKey: key, ParentID: po.Puid, PromoteID: po.PromoteID, IDCard: po.IDCard}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
bySource := make(map[string][]int64)
|
||||
for key := range known {
|
||||
if !unknown[key.ID] {
|
||||
bySource[key.SourceDB] = append(bySource[key.SourceDB], key.ID)
|
||||
}
|
||||
}
|
||||
sources := make([]string, 0, len(bySource))
|
||||
for source := range bySource {
|
||||
sources = append(sources, source)
|
||||
}
|
||||
sort.Strings(sources)
|
||||
// MySQL 5.7 的多列 IN 在部分批次退化为全表扫描;固定平台后
|
||||
// 对 ID 做范围查询,仍完整匹配复合主键,并按 ID 顺序减少随机读页。
|
||||
for _, source := range sources {
|
||||
ids := bySource[source]
|
||||
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
|
||||
for start := 0; start < len(ids); start += 500 {
|
||||
if err := read(db.Table("tab_user").Where("source_db=? AND id IN ?", source, ids[start:min(start+500, len(ids))])); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
ids := make([]int64, 0, len(unknown))
|
||||
for id := range unknown {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
|
||||
for start := 0; start < len(ids); start += 500 {
|
||||
if err := read(db.Table("tab_user").Where("id IN ?", ids[start:min(start+500, len(ids))])); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func reportRegistrationQuery(db *gorm.DB) (*gorm.DB, error) {
|
||||
q := db.Table("tab_user")
|
||||
if db.Dialector.Name() != "mysql" || !db.Migrator().HasIndex("tab_user", "idx_sw_user_registration") {
|
||||
|
||||
Reference in New Issue
Block a user