151 lines
6.4 KiB
Go
151 lines
6.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/glebarez/sqlite"
|
|
"gorm.io/gorm"
|
|
businessbiz "kra/internal/biz/business"
|
|
taskbiz "kra/internal/biz/task"
|
|
businessdata "kra/internal/data/business"
|
|
taskdata "kra/internal/data/task"
|
|
"kra/internal/server/handler"
|
|
"kra/internal/server/router"
|
|
taskservice "kra/internal/service/task"
|
|
"kra/internal/worker"
|
|
platformtask "kra/pkg/task"
|
|
)
|
|
|
|
type reportTaskHTTPData struct{ businessHTTPData }
|
|
|
|
func (reportTaskHTTPData) DatabaseReady() bool { return true }
|
|
|
|
func TestReportBuildThroughNativeTaskHTTP(t *testing.T) {
|
|
db, err := gorm.Open(sqlite.Open(filepath.Join(t.TempDir(), "report-task.db")), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pool, _ := db.DB()
|
|
t.Cleanup(func() { _ = pool.Close() })
|
|
for _, step := range append(taskdata.Migrations(), businessdata.Migrations()...) {
|
|
if err := step.Migrate(db); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
for _, sql := range []string{
|
|
"CREATE TABLE tab_user(id INTEGER,source_db TEXT,puid INTEGER,promote_id INTEGER,fgame_id INTEGER,idcard TEXT,register_time TEXT)",
|
|
"CREATE TABLE tab_user_day_login(user_id INTEGER,source_db TEXT,promote_id INTEGER,game_id INTEGER,login_time INTEGER)",
|
|
"CREATE TABLE tab_user_play_info(user_id INTEGER,source_db TEXT,promote_id INTEGER,game_id INTEGER,server_id TEXT,create_time INTEGER,play_time INTEGER)",
|
|
"CREATE TABLE tab_spend(user_id INTEGER,source_db TEXT,promote_id INTEGER,game_id INTEGER,server_id TEXT,pay_time INTEGER,pay_status INTEGER,pay_amount DECIMAL(20,2))",
|
|
"CREATE TABLE tab_game(id INTEGER,source_db TEXT,game_name TEXT)",
|
|
"INSERT INTO tab_game VALUES(1,'lx','核验游戏')",
|
|
"CREATE TABLE tab_sw_report_day(id INTEGER PRIMARY KEY,stat_date DATE,source_db TEXT,promote_id INTEGER,game_id INTEGER,game_name TEXT,dedup_mode INTEGER,new_register_cnt INTEGER,active_cnt INTEGER,pay_cnt INTEGER,new_pay_cnt INTEGER,total_pay DECIMAL(20,2))",
|
|
"CREATE TABLE tab_sw_report_day_key(id INTEGER PRIMARY KEY,stat_date DATE,source_db TEXT,promote_id INTEGER,game_id INTEGER,game_name TEXT,dedup_mode INTEGER,metric INTEGER,identity_key TEXT)",
|
|
"CREATE TABLE tab_sw_report_server_day(id INTEGER PRIMARY KEY,stat_date DATE,source_db TEXT,promote_id INTEGER,game_id INTEGER,game_name TEXT,server_num TEXT,dedup_mode INTEGER,new_register_cnt INTEGER,active_cnt INTEGER,pay_cnt INTEGER,total_pay DECIMAL(20,2))",
|
|
"CREATE TABLE tab_sw_report_server_day_key(id INTEGER PRIMARY KEY,stat_date DATE,source_db TEXT,promote_id INTEGER,game_id INTEGER,game_name TEXT,server_num TEXT,dedup_mode INTEGER,metric INTEGER,identity_key TEXT)",
|
|
} {
|
|
if err := db.Exec(sql).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
stamp := time.Date(2026, 11, 4, 12, 0, 0, 0, time.FixedZone("Asia/Shanghai", 8*3600)).Unix()
|
|
for _, sql := range []string{"INSERT INTO tab_user VALUES(1,'lx',0,10,1,'aX',?)", "INSERT INTO tab_user_day_login VALUES(1,'lx',10,1,?)", "INSERT INTO tab_spend VALUES(1,'lx',10,1,'001',?,1,12.50)"} {
|
|
if err := db.Exec(sql, stamp).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if err := db.Exec("INSERT INTO tab_user_play_info VALUES(1,'lx',10,1,'001',?,?)", stamp, stamp).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
provider := businessHTTPData{db}
|
|
registry := platformtask.NewRegistry()
|
|
tasks := taskbiz.NewTaskUsecaseWithRegistry(taskdata.NewTaskRepo(reportTaskHTTPData{provider}), registry)
|
|
reports := businessbiz.NewReportBuildUsecase(businessdata.NewReportBuildRepo(provider))
|
|
worker.NewTaskMethods(tasks, nil, nil, nil, reports, nil).RegisterTasks(registry)
|
|
scheduler := worker.NewTaskScheduler(tasks, nil, worker.NewTaskExecutorWithRegistry(tasks, registry), nil)
|
|
defer func() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
_ = scheduler.Stop(ctx)
|
|
}()
|
|
h := handler.NewTask(taskservice.NewTaskService(taskbiz.NewTaskApplicationUsecase(tasks, scheduler)))
|
|
engine := gin.New()
|
|
router.RegisterTask(engine.Group(""), h)
|
|
srv := httptest.NewServer(engine)
|
|
defer srv.Close()
|
|
call := func(method, path string, body any) map[string]any {
|
|
t.Helper()
|
|
raw, _ := json.Marshal(body)
|
|
req, _ := http.NewRequest(method, srv.URL+"/timedTask/"+path, bytes.NewReader(raw))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
res, err := srv.Client().Do(req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer res.Body.Close()
|
|
var value map[string]any
|
|
if err := json.NewDecoder(res.Body).Decode(&value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if value["code"] != float64(0) {
|
|
t.Fatalf("原生任务接口失败: %+v", value)
|
|
}
|
|
return value["data"].(map[string]any)
|
|
}
|
|
methods := call("GET", "getRegisteredMethods", nil)["methods"].([]any)
|
|
if len(methods) != 9 {
|
|
t.Fatalf("六个商务汇总方法未注册: %d", len(methods))
|
|
}
|
|
for index, method := range []string{"swReportDayBackfillTask", "swReportServerDayBackfillTask"} {
|
|
name := fmt.Sprintf("隔离汇总任务%d", index)
|
|
call("POST", "createTimedTask", map[string]any{"name": name, "spec": "@daily", "executorType": "method", "methodName": method, "params": map[string]any{"startDate": "2026-11-04", "endDate": "2026-11-04"}, "enabled": false})
|
|
var id uint
|
|
if err := db.Table("sys_timed_tasks").Select("id").Where("name=?", name).Scan(&id).Error; err != nil || id == 0 {
|
|
t.Fatal("任务创建未落库")
|
|
}
|
|
call("POST", "triggerTimedTask", map[string]any{"id": id})
|
|
deadline := time.Now().Add(8 * time.Second)
|
|
done := false
|
|
for time.Now().Before(deadline) {
|
|
logs := call("GET", fmt.Sprintf("getTimedTaskLogList?taskId=%d&page=1&pageSize=10", id), nil)["list"].([]any)
|
|
if len(logs) > 0 {
|
|
if logs[0].(map[string]any)["status"] != "success" {
|
|
t.Fatalf("汇总任务失败: %+v", logs)
|
|
}
|
|
done = true
|
|
break
|
|
}
|
|
time.Sleep(20 * time.Millisecond)
|
|
}
|
|
if !done {
|
|
t.Fatal("未等到汇总任务完成")
|
|
}
|
|
}
|
|
for _, table := range []string{"tab_sw_report_day", "tab_sw_report_server_day"} {
|
|
var rows []struct {
|
|
TotalPay string
|
|
NewRegisterCnt, ActiveCnt, PayCnt int
|
|
}
|
|
if err := db.Table(table).Scan(&rows).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(rows) != 2 || rows[0].TotalPay != "12.5" || rows[0].NewRegisterCnt != 1 || rows[0].ActiveCnt != 1 || rows[0].PayCnt != 1 {
|
|
t.Fatalf("任务没有实际生成双口径汇总: %+v", rows)
|
|
}
|
|
}
|
|
var enabled int64
|
|
db.Table("sys_timed_tasks").Where("enabled=1").Count(&enabled)
|
|
if enabled != 0 {
|
|
t.Fatal("手动回跑不应启用自动计划")
|
|
}
|
|
}
|