This commit is contained in:
2025-09-12 01:15:09 +08:00
parent c563b2266b
commit e05ad9e223
103 changed files with 20034 additions and 1041 deletions

View File

@@ -0,0 +1,498 @@
package events
import (
"context"
"encoding/json"
"fmt"
"time"
"go.uber.org/zap"
"tyapi-server/internal/domains/statistics/events"
"tyapi-server/internal/domains/statistics/repositories"
"tyapi-server/internal/infrastructure/statistics/cache"
)
// StatisticsEventHandler 统计事件处理器
type StatisticsEventHandler struct {
metricRepo repositories.StatisticsRepository
reportRepo repositories.StatisticsReportRepository
dashboardRepo repositories.StatisticsDashboardRepository
cache *cache.RedisStatisticsCache
logger *zap.Logger
}
// NewStatisticsEventHandler 创建统计事件处理器
func NewStatisticsEventHandler(
metricRepo repositories.StatisticsRepository,
reportRepo repositories.StatisticsReportRepository,
dashboardRepo repositories.StatisticsDashboardRepository,
cache *cache.RedisStatisticsCache,
logger *zap.Logger,
) *StatisticsEventHandler {
return &StatisticsEventHandler{
metricRepo: metricRepo,
reportRepo: reportRepo,
dashboardRepo: dashboardRepo,
cache: cache,
logger: logger,
}
}
// HandleMetricCreatedEvent 处理指标创建事件
func (h *StatisticsEventHandler) HandleMetricCreatedEvent(ctx context.Context, event *events.MetricCreatedEvent) error {
h.logger.Info("处理指标创建事件",
zap.String("metric_id", event.MetricID),
zap.String("metric_type", event.MetricType),
zap.String("metric_name", event.MetricName),
zap.Float64("value", event.Value))
// 更新实时指标缓存
err := h.cache.UpdateRealtimeMetric(ctx, event.MetricType, event.MetricName, event.Value, 1*time.Hour)
if err != nil {
h.logger.Error("更新实时指标缓存失败", zap.Error(err))
// 不返回错误,避免影响主流程
}
// 清理相关缓存
err = h.cache.DeleteMetricsByType(ctx, event.MetricType)
if err != nil {
h.logger.Error("清理指标类型缓存失败", zap.Error(err))
}
return nil
}
// HandleMetricUpdatedEvent 处理指标更新事件
func (h *StatisticsEventHandler) HandleMetricUpdatedEvent(ctx context.Context, event *events.MetricUpdatedEvent) error {
h.logger.Info("处理指标更新事件",
zap.String("metric_id", event.MetricID),
zap.Float64("old_value", event.OldValue),
zap.Float64("new_value", event.NewValue))
// 获取指标信息
metric, err := h.metricRepo.FindByID(ctx, event.MetricID)
if err != nil {
h.logger.Error("查询指标失败", zap.Error(err))
return err
}
// 更新实时指标缓存
err = h.cache.UpdateRealtimeMetric(ctx, metric.MetricType, metric.MetricName, event.NewValue, 1*time.Hour)
if err != nil {
h.logger.Error("更新实时指标缓存失败", zap.Error(err))
}
// 清理相关缓存
err = h.cache.DeleteMetric(ctx, event.MetricID)
if err != nil {
h.logger.Error("清理指标缓存失败", zap.Error(err))
}
err = h.cache.DeleteMetricsByType(ctx, metric.MetricType)
if err != nil {
h.logger.Error("清理指标类型缓存失败", zap.Error(err))
}
return nil
}
// HandleMetricAggregatedEvent 处理指标聚合事件
func (h *StatisticsEventHandler) HandleMetricAggregatedEvent(ctx context.Context, event *events.MetricAggregatedEvent) error {
h.logger.Info("处理指标聚合事件",
zap.String("metric_type", event.MetricType),
zap.String("dimension", event.Dimension),
zap.Int("record_count", event.RecordCount),
zap.Float64("total_value", event.TotalValue))
// 清理相关缓存
err := h.cache.ClearRealtimeCache(ctx)
if err != nil {
h.logger.Error("清理实时缓存失败", zap.Error(err))
}
err = h.cache.ClearMetricsCache(ctx)
if err != nil {
h.logger.Error("清理指标缓存失败", zap.Error(err))
}
return nil
}
// HandleReportCreatedEvent 处理报告创建事件
func (h *StatisticsEventHandler) HandleReportCreatedEvent(ctx context.Context, event *events.ReportCreatedEvent) error {
h.logger.Info("处理报告创建事件",
zap.String("report_id", event.ReportID),
zap.String("report_type", event.ReportType),
zap.String("title", event.Title))
// 获取报告信息
report, err := h.reportRepo.FindByID(ctx, event.ReportID)
if err != nil {
h.logger.Error("查询报告失败", zap.Error(err))
return err
}
// 设置报告缓存
err = h.cache.SetReport(ctx, report, 24*time.Hour)
if err != nil {
h.logger.Error("设置报告缓存失败", zap.Error(err))
}
return nil
}
// HandleReportGenerationStartedEvent 处理报告生成开始事件
func (h *StatisticsEventHandler) HandleReportGenerationStartedEvent(ctx context.Context, event *events.ReportGenerationStartedEvent) error {
h.logger.Info("处理报告生成开始事件",
zap.String("report_id", event.ReportID),
zap.String("generated_by", event.GeneratedBy))
// 获取报告信息
report, err := h.reportRepo.FindByID(ctx, event.ReportID)
if err != nil {
h.logger.Error("查询报告失败", zap.Error(err))
return err
}
// 更新报告缓存
err = h.cache.SetReport(ctx, report, 24*time.Hour)
if err != nil {
h.logger.Error("更新报告缓存失败", zap.Error(err))
}
return nil
}
// HandleReportCompletedEvent 处理报告完成事件
func (h *StatisticsEventHandler) HandleReportCompletedEvent(ctx context.Context, event *events.ReportCompletedEvent) error {
h.logger.Info("处理报告完成事件",
zap.String("report_id", event.ReportID),
zap.Int("content_size", event.ContentSize))
// 获取报告信息
report, err := h.reportRepo.FindByID(ctx, event.ReportID)
if err != nil {
h.logger.Error("查询报告失败", zap.Error(err))
return err
}
// 更新报告缓存
err = h.cache.SetReport(ctx, report, 7*24*time.Hour) // 报告完成后缓存7天
if err != nil {
h.logger.Error("更新报告缓存失败", zap.Error(err))
}
return nil
}
// HandleReportFailedEvent 处理报告失败事件
func (h *StatisticsEventHandler) HandleReportFailedEvent(ctx context.Context, event *events.ReportFailedEvent) error {
h.logger.Info("处理报告失败事件",
zap.String("report_id", event.ReportID),
zap.String("reason", event.Reason))
// 获取报告信息
report, err := h.reportRepo.FindByID(ctx, event.ReportID)
if err != nil {
h.logger.Error("查询报告失败", zap.Error(err))
return err
}
// 更新报告缓存
err = h.cache.SetReport(ctx, report, 1*time.Hour) // 失败报告只缓存1小时
if err != nil {
h.logger.Error("更新报告缓存失败", zap.Error(err))
}
return nil
}
// HandleDashboardCreatedEvent 处理仪表板创建事件
func (h *StatisticsEventHandler) HandleDashboardCreatedEvent(ctx context.Context, event *events.DashboardCreatedEvent) error {
h.logger.Info("处理仪表板创建事件",
zap.String("dashboard_id", event.DashboardID),
zap.String("name", event.Name),
zap.String("user_role", event.UserRole))
// 获取仪表板信息
dashboard, err := h.dashboardRepo.FindByID(ctx, event.DashboardID)
if err != nil {
h.logger.Error("查询仪表板失败", zap.Error(err))
return err
}
// 设置仪表板缓存
err = h.cache.SetDashboard(ctx, dashboard, 24*time.Hour)
if err != nil {
h.logger.Error("设置仪表板缓存失败", zap.Error(err))
}
// 清理仪表板数据缓存
err = h.cache.DeleteDashboardData(ctx, event.UserRole)
if err != nil {
h.logger.Error("清理仪表板数据缓存失败", zap.Error(err))
}
return nil
}
// HandleDashboardUpdatedEvent 处理仪表板更新事件
func (h *StatisticsEventHandler) HandleDashboardUpdatedEvent(ctx context.Context, event *events.DashboardUpdatedEvent) error {
h.logger.Info("处理仪表板更新事件",
zap.String("dashboard_id", event.DashboardID),
zap.String("updated_by", event.UpdatedBy))
// 获取仪表板信息
dashboard, err := h.dashboardRepo.FindByID(ctx, event.DashboardID)
if err != nil {
h.logger.Error("查询仪表板失败", zap.Error(err))
return err
}
// 更新仪表板缓存
err = h.cache.SetDashboard(ctx, dashboard, 24*time.Hour)
if err != nil {
h.logger.Error("更新仪表板缓存失败", zap.Error(err))
}
// 清理仪表板数据缓存
err = h.cache.DeleteDashboardData(ctx, dashboard.UserRole)
if err != nil {
h.logger.Error("清理仪表板数据缓存失败", zap.Error(err))
}
return nil
}
// HandleDashboardActivatedEvent 处理仪表板激活事件
func (h *StatisticsEventHandler) HandleDashboardActivatedEvent(ctx context.Context, event *events.DashboardActivatedEvent) error {
h.logger.Info("处理仪表板激活事件",
zap.String("dashboard_id", event.DashboardID),
zap.String("activated_by", event.ActivatedBy))
// 获取仪表板信息
dashboard, err := h.dashboardRepo.FindByID(ctx, event.DashboardID)
if err != nil {
h.logger.Error("查询仪表板失败", zap.Error(err))
return err
}
// 更新仪表板缓存
err = h.cache.SetDashboard(ctx, dashboard, 24*time.Hour)
if err != nil {
h.logger.Error("更新仪表板缓存失败", zap.Error(err))
}
// 清理仪表板数据缓存
err = h.cache.DeleteDashboardData(ctx, dashboard.UserRole)
if err != nil {
h.logger.Error("清理仪表板数据缓存失败", zap.Error(err))
}
return nil
}
// HandleDashboardDeactivatedEvent 处理仪表板停用事件
func (h *StatisticsEventHandler) HandleDashboardDeactivatedEvent(ctx context.Context, event *events.DashboardDeactivatedEvent) error {
h.logger.Info("处理仪表板停用事件",
zap.String("dashboard_id", event.DashboardID),
zap.String("deactivated_by", event.DeactivatedBy))
// 获取仪表板信息
dashboard, err := h.dashboardRepo.FindByID(ctx, event.DashboardID)
if err != nil {
h.logger.Error("查询仪表板失败", zap.Error(err))
return err
}
// 更新仪表板缓存
err = h.cache.SetDashboard(ctx, dashboard, 24*time.Hour)
if err != nil {
h.logger.Error("更新仪表板缓存失败", zap.Error(err))
}
// 清理仪表板数据缓存
err = h.cache.DeleteDashboardData(ctx, dashboard.UserRole)
if err != nil {
h.logger.Error("清理仪表板数据缓存失败", zap.Error(err))
}
return nil
}
// ================ 事件分发器 ================
// EventDispatcher 事件分发器
type EventDispatcher struct {
handlers map[string][]func(context.Context, interface{}) error
logger *zap.Logger
}
// NewEventDispatcher 创建事件分发器
func NewEventDispatcher(logger *zap.Logger) *EventDispatcher {
return &EventDispatcher{
handlers: make(map[string][]func(context.Context, interface{}) error),
logger: logger,
}
}
// RegisterHandler 注册事件处理器
func (d *EventDispatcher) RegisterHandler(eventType string, handler func(context.Context, interface{}) error) {
if d.handlers[eventType] == nil {
d.handlers[eventType] = make([]func(context.Context, interface{}) error, 0)
}
d.handlers[eventType] = append(d.handlers[eventType], handler)
}
// Dispatch 分发事件
func (d *EventDispatcher) Dispatch(ctx context.Context, event interface{}) error {
// 获取事件类型
eventType := d.getEventType(event)
if eventType == "" {
return fmt.Errorf("无法确定事件类型")
}
// 获取处理器
handlers := d.handlers[eventType]
if len(handlers) == 0 {
d.logger.Warn("没有找到事件处理器", zap.String("event_type", eventType))
return nil
}
// 执行所有处理器
for _, handler := range handlers {
err := handler(ctx, event)
if err != nil {
d.logger.Error("事件处理器执行失败",
zap.String("event_type", eventType),
zap.Error(err))
// 继续执行其他处理器
}
}
return nil
}
// getEventType 获取事件类型
func (d *EventDispatcher) getEventType(event interface{}) string {
switch event.(type) {
case *events.MetricCreatedEvent:
return string(events.MetricCreatedEventType)
case *events.MetricUpdatedEvent:
return string(events.MetricUpdatedEventType)
case *events.MetricAggregatedEvent:
return string(events.MetricAggregatedEventType)
case *events.ReportCreatedEvent:
return string(events.ReportCreatedEventType)
case *events.ReportGenerationStartedEvent:
return string(events.ReportGenerationStartedEventType)
case *events.ReportCompletedEvent:
return string(events.ReportCompletedEventType)
case *events.ReportFailedEvent:
return string(events.ReportFailedEventType)
case *events.DashboardCreatedEvent:
return string(events.DashboardCreatedEventType)
case *events.DashboardUpdatedEvent:
return string(events.DashboardUpdatedEventType)
case *events.DashboardActivatedEvent:
return string(events.DashboardActivatedEventType)
case *events.DashboardDeactivatedEvent:
return string(events.DashboardDeactivatedEventType)
default:
return ""
}
}
// ================ 事件监听器 ================
// EventListener 事件监听器
type EventListener struct {
dispatcher *EventDispatcher
logger *zap.Logger
}
// NewEventListener 创建事件监听器
func NewEventListener(dispatcher *EventDispatcher, logger *zap.Logger) *EventListener {
return &EventListener{
dispatcher: dispatcher,
logger: logger,
}
}
// Listen 监听事件
func (l *EventListener) Listen(ctx context.Context, eventData []byte) error {
// 解析事件数据
var baseEvent events.BaseStatisticsEvent
err := json.Unmarshal(eventData, &baseEvent)
if err != nil {
return fmt.Errorf("解析事件数据失败: %w", err)
}
// 根据事件类型创建具体事件
event, err := l.createEventByType(baseEvent.Type, eventData)
if err != nil {
return fmt.Errorf("创建事件失败: %w", err)
}
// 分发事件
err = l.dispatcher.Dispatch(ctx, event)
if err != nil {
return fmt.Errorf("分发事件失败: %w", err)
}
return nil
}
// createEventByType 根据事件类型创建具体事件
func (l *EventListener) createEventByType(eventType string, eventData []byte) (interface{}, error) {
switch eventType {
case string(events.MetricCreatedEventType):
var event events.MetricCreatedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.MetricUpdatedEventType):
var event events.MetricUpdatedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.MetricAggregatedEventType):
var event events.MetricAggregatedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.ReportCreatedEventType):
var event events.ReportCreatedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.ReportGenerationStartedEventType):
var event events.ReportGenerationStartedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.ReportCompletedEventType):
var event events.ReportCompletedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.ReportFailedEventType):
var event events.ReportFailedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.DashboardCreatedEventType):
var event events.DashboardCreatedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.DashboardUpdatedEventType):
var event events.DashboardUpdatedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.DashboardActivatedEventType):
var event events.DashboardActivatedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
case string(events.DashboardDeactivatedEventType):
var event events.DashboardDeactivatedEvent
err := json.Unmarshal(eventData, &event)
return &event, err
default:
return nil, fmt.Errorf("未知的事件类型: %s", eventType)
}
}