perf: keep default ledger queries on platform time indexes
This commit is contained in:
@@ -12,6 +12,30 @@ import (
|
||||
type ledgerRepo struct{ data Provider }
|
||||
|
||||
func NewLedgerRepo(data Provider) business.LedgerRepo { return &ledgerRepo{data: data} }
|
||||
|
||||
// Enumerating the stored platform codes lets MySQL use the leading column of
|
||||
// the time indexes even when the caller requests every platform. Read them
|
||||
// from the table so historical or newly imported codes remain in scope.
|
||||
func resolveLedgerSources(db *gorm.DB, table string, filter *business.LedgerFilter) error {
|
||||
if len(filter.Sources) > 0 {
|
||||
return nil
|
||||
}
|
||||
var sources []struct{ SourceDB *string }
|
||||
if err := db.Table(table).Select("source_db").Distinct().Scan(&sources).Error; err != nil {
|
||||
return business.ErrStorage
|
||||
}
|
||||
for _, source := range sources {
|
||||
if source.SourceDB == nil {
|
||||
// Legacy production columns are NOT NULL. Preserve unfiltered
|
||||
// semantics if another supported storage layout contains NULL.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
for _, source := range sources {
|
||||
filter.Sources = append(filter.Sources, *source.SourceDB)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func ledgerBasePromotes(db *gorm.DB, scope business.LedgerScope, filter business.LedgerFilter, alias string) *gorm.DB {
|
||||
q := db.Table("tab_promote " + alias)
|
||||
if len(filter.Sources) > 0 {
|
||||
@@ -149,6 +173,9 @@ func (r *ledgerRepo) Registrations(ctx context.Context, scope business.LedgerSco
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := resolveLedgerSources(db, "tab_user", &filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := registrationQuery(db, scope, filter, timeExpression)
|
||||
if err := q.Count(&page.Total).Error; err != nil {
|
||||
return nil, business.ErrStorage
|
||||
@@ -274,6 +301,9 @@ func (r *ledgerRepo) Spends(ctx context.Context, scope business.LedgerScope, fil
|
||||
page.TotalPayAmount = nil
|
||||
return page, nil
|
||||
}
|
||||
if err := resolveLedgerSources(db, "tab_spend", &filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := spendQuery(db, scope, filter, false)
|
||||
if err := q.Count(&page.Total).Error; err != nil {
|
||||
return nil, business.ErrStorage
|
||||
|
||||
@@ -3,12 +3,54 @@ package business
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"kra/internal/biz/business"
|
||||
)
|
||||
|
||||
func TestUnfilteredLedgerKeepsEveryStoredPlatform(t *testing.T) {
|
||||
db, repo, _, filter := prepareLedgerData(t)
|
||||
for _, query := range []string{
|
||||
"INSERT INTO tab_user(id,source_db,register_time,promote_id,puid) VALUES(90,'historical','1500',0,0)",
|
||||
"INSERT INTO tab_spend(id,source_db,user_id,pay_amount,pay_time,pay_status,promote_id) VALUES(990,'historical',90,12.34,1500,1,0)",
|
||||
} {
|
||||
if err := db.Exec(query).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
scope := business.LedgerScope{Viewer: business.UserScope{All: true}, Unrestricted: true, IncludeSub: true}
|
||||
filter.Sources = nil
|
||||
registrations, err := repo.Registrations(context.Background(), scope, filter, business.LedgerListOptions{Limit: 30})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
spends, err := repo.Spends(context.Background(), scope, filter, business.LedgerListOptions{Limit: 30})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
filter.Sources = []string{"lx", "hw", "historical"}
|
||||
expectedRegistrations, err := repo.Registrations(context.Background(), scope, filter, business.LedgerListOptions{Limit: 30})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expectedSpends, err := repo.Spends(context.Background(), scope, filter, business.LedgerListOptions{Limit: 30})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(registrations, expectedRegistrations) || !reflect.DeepEqual(spends, expectedSpends) {
|
||||
t.Fatal("omitted platform filter lost historical, official or orphan rows")
|
||||
}
|
||||
if err := db.Exec("INSERT INTO tab_user(id,source_db,register_time,promote_id,puid) VALUES(91,NULL,'1500',0,0)").Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
all := business.LedgerFilter{}
|
||||
if err := resolveLedgerSources(db, "tab_user", &all); err != nil || len(all.Sources) != 0 {
|
||||
t.Fatalf("NULL platform must retain unfiltered semantics: %+v %v", all, err)
|
||||
}
|
||||
}
|
||||
|
||||
func prepareLedgerData(t *testing.T) (*gorm.DB, business.LedgerRepo, business.LedgerScope, business.LedgerFilter) {
|
||||
t.Helper()
|
||||
db, _ := prepareChannels(t)
|
||||
|
||||
Reference in New Issue
Block a user