|
|
@@ -4,10 +4,12 @@ import (
|
|
|
"context"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
+ "fwh-toolbox-server/config"
|
|
|
"fwh-toolbox-server/domain"
|
|
|
"fwh-toolbox-server/repositories"
|
|
|
task_core "fwh-toolbox-server/task/core"
|
|
|
task_pg "fwh-toolbox-server/task/plugin"
|
|
|
+ "sync"
|
|
|
"time"
|
|
|
|
|
|
"github.com/google/uuid"
|
|
|
@@ -45,18 +47,48 @@ type TaskCore interface {
|
|
|
type SimCardSyncOnePagePayload struct {
|
|
|
Size uint64 `json:"size"`
|
|
|
Page uint64 `json:"page"`
|
|
|
+ Date string `json:"date,omitempty"` // UTC collection date
|
|
|
+}
|
|
|
+
|
|
|
+type simCardPageBatch struct {
|
|
|
+ Date string
|
|
|
+ Pages []domain.SimCardRunPage
|
|
|
+ Info []domain.SimCardInfo
|
|
|
}
|
|
|
|
|
|
type SimCardProcessor struct {
|
|
|
- // ... fields for struct
|
|
|
- infoCacheMap map[string][]domain.SimCardInfo
|
|
|
+ cacheMu sync.Mutex
|
|
|
+ infoCacheMap map[string][]simCardPageBatch
|
|
|
+ webhook string
|
|
|
+ secret string
|
|
|
+}
|
|
|
+
|
|
|
+func (processor *SimCardProcessor) putBatches(key string, batches []simCardPageBatch) {
|
|
|
+ processor.cacheMu.Lock()
|
|
|
+ defer processor.cacheMu.Unlock()
|
|
|
+ processor.infoCacheMap[key] = batches
|
|
|
+}
|
|
|
+
|
|
|
+func (processor *SimCardProcessor) getBatches(key string) ([]simCardPageBatch, bool) {
|
|
|
+ processor.cacheMu.Lock()
|
|
|
+ defer processor.cacheMu.Unlock()
|
|
|
+ batches, ok := processor.infoCacheMap[key]
|
|
|
+ return batches, ok
|
|
|
+}
|
|
|
+
|
|
|
+func (processor *SimCardProcessor) deleteBatches(key string) {
|
|
|
+ processor.cacheMu.Lock()
|
|
|
+ defer processor.cacheMu.Unlock()
|
|
|
+ delete(processor.infoCacheMap, key)
|
|
|
}
|
|
|
|
|
|
var TaskClient *asynq.Client
|
|
|
|
|
|
-func InitSimCardTaskQueue(tc *task_core.TaskCore) {
|
|
|
+func InitSimCardTaskQueue(tc *task_core.TaskCore, appConfig *config.AppConfig) {
|
|
|
processor := &SimCardProcessor{
|
|
|
- infoCacheMap: make(map[string][]domain.SimCardInfo),
|
|
|
+ infoCacheMap: make(map[string][]simCardPageBatch),
|
|
|
+ webhook: appConfig.SimCardDingTalkWebhook,
|
|
|
+ secret: appConfig.SimCardDingTalkSecret,
|
|
|
}
|
|
|
|
|
|
// 注册SmartHub收集任务处理函数
|
|
|
@@ -68,23 +100,28 @@ func InitSimCardTaskQueue(tc *task_core.TaskCore) {
|
|
|
|
|
|
// 注册SimCard批处理任务
|
|
|
mux.HandleFunc(TaskTypeSimCardBulk, processor.handleSimCardBulkTask)
|
|
|
+ mux.HandleFunc(taskTypeSimCardDailyReport, processor.handleSimCardDailyReport)
|
|
|
|
|
|
// 注册SimCard组聚合器
|
|
|
aggManager := task_pg.NewAggregatorManager()
|
|
|
err := aggManager.Register(GroupNameSimCardAggregation, func(tasks []*asynq.Task) *asynq.Task {
|
|
|
- var aggInfoList []domain.SimCardInfo
|
|
|
+ var batches []simCardPageBatch
|
|
|
for _, t := range tasks {
|
|
|
payloadStr := t.Payload()
|
|
|
|
|
|
- infoList := processor.infoCacheMap[string(payloadStr)]
|
|
|
- defer delete(processor.infoCacheMap, string(payloadStr))
|
|
|
+ pageBatches, ok := processor.getBatches(string(payloadStr))
|
|
|
+ if !ok {
|
|
|
+ zap.L().Error("SimCard aggregation payload missing", zap.String("key", string(payloadStr)))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ defer processor.deleteBatches(string(payloadStr))
|
|
|
|
|
|
- aggInfoList = append(aggInfoList, infoList...)
|
|
|
+ batches = append(batches, pageBatches...)
|
|
|
}
|
|
|
|
|
|
uuidStr := uuid.NewString()
|
|
|
- processor.infoCacheMap[uuidStr] = aggInfoList
|
|
|
- zap.L().Debug("SimCardBulk get aggInfoList.", zap.Int("len", len(aggInfoList)))
|
|
|
+ processor.putBatches(uuidStr, batches)
|
|
|
+ zap.L().Debug("SimCardBulk get batches.", zap.Int("len", len(batches)))
|
|
|
|
|
|
bulkTask := asynq.NewTask(
|
|
|
TaskTypeSimCardBulk,
|
|
|
@@ -241,7 +278,7 @@ func CreateTaskSimCardCollect() error {
|
|
|
}
|
|
|
|
|
|
// 保存SimCard信息到数据库
|
|
|
-func (processor *SimCardProcessor) saveSimCardInfo(infoList []domain.SimCardInfo) error {
|
|
|
+func (processor *SimCardProcessor) saveSimCardInfo(infoList []domain.SimCardInfo, date time.Time) error {
|
|
|
zap.L().Info("saveSimCardInfo", zap.Int("Num", len(infoList)))
|
|
|
|
|
|
// 保存基本信息
|
|
|
@@ -255,15 +292,15 @@ func (processor *SimCardProcessor) saveSimCardInfo(infoList []domain.SimCardInfo
|
|
|
dayDataList := []domain.SimCardDayData{}
|
|
|
for _, info := range infoList {
|
|
|
dayData := domain.SimCardDayData{
|
|
|
- SimId: info.GICCID, // GICCID
|
|
|
- UpdateTime: info.UpdateTime, // UTC时间
|
|
|
- Month: info.Month, // 统计月份 格式:yyyy-MM
|
|
|
- AllDataUsage: info.AllDataUsage, // 月数据用量(KB)
|
|
|
- Day: uint8(time.Now().UTC().Day()), // 当天日期值 1-31
|
|
|
+ SimId: info.GICCID, // GICCID
|
|
|
+ UpdateTime: info.UpdateTime, // UTC时间
|
|
|
+ Month: info.Month, // 统计月份 格式:yyyy-MM
|
|
|
+ AllDataUsage: info.AllDataUsage, // 月数据用量(KB)
|
|
|
+ Day: uint8(date.Day()), // 当天日期值 1-31
|
|
|
DailyUsage: domain.SimCardDailyUsage{
|
|
|
- UpdateTime: info.UpdateTime, // UTC时间
|
|
|
- Day: time.Now().UTC().Format(time.DateOnly), // 统计日期 格式:yyyy-MM-DD
|
|
|
- DataUsage: info.AllDataUsage, // 数据用量(KB)
|
|
|
+ UpdateTime: info.UpdateTime, // UTC时间
|
|
|
+ Day: date.Format(time.DateOnly), // 统计日期 格式:yyyy-MM-DD
|
|
|
+ DataUsage: info.AllDataUsage, // 数据用量(KB)
|
|
|
}, // 日用量数据信息
|
|
|
}
|
|
|
dayDataList = append(dayDataList, dayData)
|
|
|
@@ -282,12 +319,35 @@ func (processor *SimCardProcessor) saveSimCardInfo(infoList []domain.SimCardInfo
|
|
|
// 处理SimCard批处理任务
|
|
|
func (processor *SimCardProcessor) handleSimCardBulkTask(ctx context.Context, task *asynq.Task) error {
|
|
|
payloadStr := task.Payload()
|
|
|
- originalList := processor.infoCacheMap[string(payloadStr)]
|
|
|
- defer delete(processor.infoCacheMap, string(payloadStr))
|
|
|
-
|
|
|
- // infoList := make([]domain.SimCardInfo, len(originalList))
|
|
|
- // copy(infoList, originalList) // 这里使用拷贝,防止引用被删除
|
|
|
- infoList := originalList
|
|
|
-
|
|
|
- return processor.saveSimCardInfo(infoList)
|
|
|
+ batches, ok := processor.getBatches(string(payloadStr))
|
|
|
+ if !ok {
|
|
|
+ return fmt.Errorf("SIM card bulk payload missing: %s", string(payloadStr))
|
|
|
+ }
|
|
|
+ byDate := make(map[string]*simCardPageBatch)
|
|
|
+ for _, batch := range batches {
|
|
|
+ combined := byDate[batch.Date]
|
|
|
+ if combined == nil {
|
|
|
+ combined = &simCardPageBatch{Date: batch.Date}
|
|
|
+ byDate[batch.Date] = combined
|
|
|
+ }
|
|
|
+ combined.Pages = append(combined.Pages, batch.Pages...)
|
|
|
+ combined.Info = append(combined.Info, batch.Info...)
|
|
|
+ }
|
|
|
+ for dateStr, batch := range byDate {
|
|
|
+ date, err := time.Parse(time.DateOnly, dateStr)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if err := processor.saveSimCardInfo(batch.Info, date); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if err := repositories.MarkSimCardPagesSaved(dateStr, batch.Pages); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if err := processor.enqueueSimCardReportIfComplete(dateStr); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ processor.deleteBatches(string(payloadStr))
|
|
|
+ return nil
|
|
|
}
|