fwhTaskSiteAnalysis.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package fwhQueue
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "fwh-toolbox-server/domain"
  7. "fwh-toolbox-server/jobs"
  8. "fwh-toolbox-server/repositories"
  9. "time"
  10. "github.com/hibiken/asynq"
  11. "go.uber.org/zap"
  12. )
  13. // handleSiteAnalysis 是站点分析任务的 Asynq handler
  14. func handleSiteAnalysis(ctx context.Context, task *asynq.Task) error {
  15. var payload domain.TaskSiteAnalysis
  16. if err := json.Unmarshal(task.Payload(), &payload); err != nil {
  17. return fmt.Errorf("unmarshal SiteAnalysis payload: %w", err)
  18. }
  19. taskId := payload.Id.Hex()
  20. // 更新运行状态
  21. if err := repositories.UpdateSiteAnalysisResult(payload.Id, domain.ProgressRunning); err != nil {
  22. zap.L().Error("[SiteAnalysis] 更新状态失败(Running)", zap.String("id", taskId))
  23. return err
  24. }
  25. // 执行分析逻辑
  26. err := executeSiteAnalysis(ctx, payload)
  27. if err != nil {
  28. zap.L().Error("[SiteAnalysis] 任务执行失败", zap.String("id", taskId), zap.String("err", err.Error()))
  29. repositories.UpdateSiteAnalysisResult(payload.Id, domain.ProgressError)
  30. return nil // 返回 nil 避免 Asynq 重试(业务错误不需要重试)
  31. }
  32. zap.L().Info("[SiteAnalysis] 任务执行成功", zap.String("id", taskId))
  33. repositories.UpdateSiteAnalysisResult(payload.Id, domain.ProgressComplete)
  34. return nil
  35. }
  36. // executeSiteAnalysis 执行站点分析
  37. func executeSiteAnalysis(ctx context.Context, payload domain.TaskSiteAnalysis) error {
  38. // 解析时间范围
  39. startTime, err := time.Parse(time.DateOnly, payload.TimePeriod[0])
  40. if err != nil {
  41. return fmt.Errorf("startTime 格式错误: %w", err)
  42. }
  43. endTime, err := time.Parse(time.DateOnly, payload.TimePeriod[1])
  44. if err != nil {
  45. return fmt.Errorf("endTime 格式错误: %w", err)
  46. }
  47. endTime = endTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
  48. // 创建记录数据库用于存储原始 MQTT 日志请求数据
  49. queryRecord, err := repositories.CreateSitesAnalysisRecordTable(payload.Id.Hex())
  50. if err != nil {
  51. return err
  52. }
  53. if payload.Options.EnableTimeline {
  54. // 查询 MQTT 日志 0
  55. logList_0, err := repositories.QueryMqttLogListOnTimeRange(payload.Sn, domain.MQTT_LOG_0, startTime, endTime)
  56. if err != nil {
  57. return fmt.Errorf("查询MQTT日志0失败: %w", err)
  58. }
  59. for _, l := range logList_0 {
  60. if err := queryRecord.InsertSitesAnalysisRecord(l); err != nil {
  61. return err
  62. }
  63. }
  64. // 查询 MQTT 日志 101
  65. logList_101, err := repositories.QueryMqttLogListOnTimeRange(payload.Sn, domain.MQTT_LOG_101, startTime, endTime)
  66. if err != nil {
  67. return fmt.Errorf("查询MQTT日志101失败: %w", err)
  68. }
  69. for _, l := range logList_101 {
  70. if err := queryRecord.InsertSitesAnalysisRecord(l); err != nil {
  71. return err
  72. }
  73. }
  74. // 查询事件触发记录
  75. eventLog, err := repositories.QueryEventOrAlarmListOnTimeRange(payload.Sn, startTime, endTime, repositories.Event)
  76. if err != nil {
  77. return fmt.Errorf("查询事件日志失败: %w", err)
  78. }
  79. time.Sleep(time.Second)
  80. // 查询告警触发记录
  81. alarmLog, err := repositories.QueryEventOrAlarmListOnTimeRange(payload.Sn, startTime, endTime, repositories.Alarm)
  82. if err != nil {
  83. return fmt.Errorf("查询告警日志失败: %w", err)
  84. }
  85. time.Sleep(time.Second)
  86. // 查询 MQTT 日志 357
  87. logList_357, err := repositories.QueryMqttLogListOnTimeRange(payload.Sn, domain.MQTT_LOG_357, startTime, endTime)
  88. if err != nil {
  89. return fmt.Errorf("查询MQTT日志357失败: %w", err)
  90. }
  91. for _, l := range logList_357 {
  92. if err := queryRecord.InsertSitesAnalysisRecord(l); err != nil {
  93. return err
  94. }
  95. }
  96. // 分析时间线数据
  97. err = jobs.AnalysisSiteTimeline(payload.Id, jobs.SiteDataSet{
  98. Log_0: logList_0,
  99. Log_101: logList_101,
  100. Log_357: logList_357,
  101. EventLog: eventLog,
  102. AlarmLog: alarmLog,
  103. })
  104. if err != nil {
  105. return fmt.Errorf("站点时间线分析失败(sn=%s): %w", payload.Sn, err)
  106. }
  107. }
  108. if payload.Options.EnableRuntime {
  109. // 查询 MQTT 日志 201
  110. logList_201, err := repositories.QueryMqttLogListOnTimeRange(payload.Sn, domain.MQTT_LOG_201, startTime, endTime)
  111. if err != nil {
  112. return fmt.Errorf("查询MQTT日志201失败: %w", err)
  113. }
  114. for _, l := range logList_201 {
  115. if err := queryRecord.InsertSitesAnalysisRecord(l); err != nil {
  116. return err
  117. }
  118. }
  119. // 分析运行时数据
  120. err = jobs.AnalysisSiteRuntime(payload.Id, jobs.SiteDataSet{
  121. Log_201: logList_201,
  122. })
  123. if err != nil {
  124. return fmt.Errorf("站点运行时数据分析失败(sn=%s): %w", payload.Sn, err)
  125. }
  126. }
  127. return nil
  128. }