585 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			585 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | package cache | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"context" | ||
|  | 	"encoding/json" | ||
|  | 	"fmt" | ||
|  | 	"time" | ||
|  | 
 | ||
|  | 	"github.com/redis/go-redis/v9" | ||
|  | 
 | ||
|  | 	"tyapi-server/internal/domains/statistics/entities" | ||
|  | ) | ||
|  | 
 | ||
|  | // RedisStatisticsCache Redis统计缓存实现 | ||
|  | type RedisStatisticsCache struct { | ||
|  | 	client *redis.Client | ||
|  | 	prefix string | ||
|  | } | ||
|  | 
 | ||
|  | // NewRedisStatisticsCache 创建Redis统计缓存 | ||
|  | func NewRedisStatisticsCache(client *redis.Client) *RedisStatisticsCache { | ||
|  | 	return &RedisStatisticsCache{ | ||
|  | 		client: client, | ||
|  | 		prefix: "statistics:", | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // ================ 指标缓存 ================ | ||
|  | 
 | ||
|  | // SetMetric 设置指标缓存 | ||
|  | func (c *RedisStatisticsCache) SetMetric(ctx context.Context, metric *entities.StatisticsMetric, expiration time.Duration) error { | ||
|  | 	if metric == nil { | ||
|  | 		return fmt.Errorf("统计指标不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getMetricKey(metric.ID) | ||
|  | 	data, err := json.Marshal(metric) | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("序列化指标失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err = c.client.Set(ctx, key, data, expiration).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("设置指标缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // GetMetric 获取指标缓存 | ||
|  | func (c *RedisStatisticsCache) GetMetric(ctx context.Context, metricID string) (*entities.StatisticsMetric, error) { | ||
|  | 	if metricID == "" { | ||
|  | 		return nil, fmt.Errorf("指标ID不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getMetricKey(metricID) | ||
|  | 	data, err := c.client.Get(ctx, key).Result() | ||
|  | 	if err != nil { | ||
|  | 		if err == redis.Nil { | ||
|  | 			return nil, nil // 缓存未命中 | ||
|  | 		} | ||
|  | 		return nil, fmt.Errorf("获取指标缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	var metric entities.StatisticsMetric | ||
|  | 	err = json.Unmarshal([]byte(data), &metric) | ||
|  | 	if err != nil { | ||
|  | 		return nil, fmt.Errorf("反序列化指标失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return &metric, nil | ||
|  | } | ||
|  | 
 | ||
|  | // DeleteMetric 删除指标缓存 | ||
|  | func (c *RedisStatisticsCache) DeleteMetric(ctx context.Context, metricID string) error { | ||
|  | 	if metricID == "" { | ||
|  | 		return fmt.Errorf("指标ID不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getMetricKey(metricID) | ||
|  | 	err := c.client.Del(ctx, key).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("删除指标缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // SetMetricsByType 设置按类型分组的指标缓存 | ||
|  | func (c *RedisStatisticsCache) SetMetricsByType(ctx context.Context, metricType string, metrics []*entities.StatisticsMetric, expiration time.Duration) error { | ||
|  | 	if metricType == "" { | ||
|  | 		return fmt.Errorf("指标类型不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getMetricsByTypeKey(metricType) | ||
|  | 	data, err := json.Marshal(metrics) | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("序列化指标列表失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err = c.client.Set(ctx, key, data, expiration).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("设置指标列表缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // GetMetricsByType 获取按类型分组的指标缓存 | ||
|  | func (c *RedisStatisticsCache) GetMetricsByType(ctx context.Context, metricType string) ([]*entities.StatisticsMetric, error) { | ||
|  | 	if metricType == "" { | ||
|  | 		return nil, fmt.Errorf("指标类型不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getMetricsByTypeKey(metricType) | ||
|  | 	data, err := c.client.Get(ctx, key).Result() | ||
|  | 	if err != nil { | ||
|  | 		if err == redis.Nil { | ||
|  | 			return nil, nil // 缓存未命中 | ||
|  | 		} | ||
|  | 		return nil, fmt.Errorf("获取指标列表缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	var metrics []*entities.StatisticsMetric | ||
|  | 	err = json.Unmarshal([]byte(data), &metrics) | ||
|  | 	if err != nil { | ||
|  | 		return nil, fmt.Errorf("反序列化指标列表失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return metrics, nil | ||
|  | } | ||
|  | 
 | ||
|  | // DeleteMetricsByType 删除按类型分组的指标缓存 | ||
|  | func (c *RedisStatisticsCache) DeleteMetricsByType(ctx context.Context, metricType string) error { | ||
|  | 	if metricType == "" { | ||
|  | 		return fmt.Errorf("指标类型不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getMetricsByTypeKey(metricType) | ||
|  | 	err := c.client.Del(ctx, key).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("删除指标列表缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // ================ 实时指标缓存 ================ | ||
|  | 
 | ||
|  | // SetRealtimeMetrics 设置实时指标缓存 | ||
|  | func (c *RedisStatisticsCache) SetRealtimeMetrics(ctx context.Context, metricType string, metrics map[string]float64, expiration time.Duration) error { | ||
|  | 	if metricType == "" { | ||
|  | 		return fmt.Errorf("指标类型不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getRealtimeMetricsKey(metricType) | ||
|  | 	data, err := json.Marshal(metrics) | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("序列化实时指标失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err = c.client.Set(ctx, key, data, expiration).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("设置实时指标缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // GetRealtimeMetrics 获取实时指标缓存 | ||
|  | func (c *RedisStatisticsCache) GetRealtimeMetrics(ctx context.Context, metricType string) (map[string]float64, error) { | ||
|  | 	if metricType == "" { | ||
|  | 		return nil, fmt.Errorf("指标类型不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getRealtimeMetricsKey(metricType) | ||
|  | 	data, err := c.client.Get(ctx, key).Result() | ||
|  | 	if err != nil { | ||
|  | 		if err == redis.Nil { | ||
|  | 			return nil, nil // 缓存未命中 | ||
|  | 		} | ||
|  | 		return nil, fmt.Errorf("获取实时指标缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	var metrics map[string]float64 | ||
|  | 	err = json.Unmarshal([]byte(data), &metrics) | ||
|  | 	if err != nil { | ||
|  | 		return nil, fmt.Errorf("反序列化实时指标失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return metrics, nil | ||
|  | } | ||
|  | 
 | ||
|  | // UpdateRealtimeMetric 更新实时指标 | ||
|  | func (c *RedisStatisticsCache) UpdateRealtimeMetric(ctx context.Context, metricType, metricName string, value float64, expiration time.Duration) error { | ||
|  | 	if metricType == "" || metricName == "" { | ||
|  | 		return fmt.Errorf("指标类型和名称不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// 获取现有指标 | ||
|  | 	metrics, err := c.GetRealtimeMetrics(ctx, metricType) | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("获取实时指标失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if metrics == nil { | ||
|  | 		metrics = make(map[string]float64) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// 更新指标值 | ||
|  | 	metrics[metricName] = value | ||
|  | 
 | ||
|  | 	// 保存更新后的指标 | ||
|  | 	err = c.SetRealtimeMetrics(ctx, metricType, metrics, expiration) | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("更新实时指标失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // ================ 报告缓存 ================ | ||
|  | 
 | ||
|  | // SetReport 设置报告缓存 | ||
|  | func (c *RedisStatisticsCache) SetReport(ctx context.Context, report *entities.StatisticsReport, expiration time.Duration) error { | ||
|  | 	if report == nil { | ||
|  | 		return fmt.Errorf("统计报告不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getReportKey(report.ID) | ||
|  | 	data, err := json.Marshal(report) | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("序列化报告失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err = c.client.Set(ctx, key, data, expiration).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("设置报告缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // GetReport 获取报告缓存 | ||
|  | func (c *RedisStatisticsCache) GetReport(ctx context.Context, reportID string) (*entities.StatisticsReport, error) { | ||
|  | 	if reportID == "" { | ||
|  | 		return nil, fmt.Errorf("报告ID不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getReportKey(reportID) | ||
|  | 	data, err := c.client.Get(ctx, key).Result() | ||
|  | 	if err != nil { | ||
|  | 		if err == redis.Nil { | ||
|  | 			return nil, nil // 缓存未命中 | ||
|  | 		} | ||
|  | 		return nil, fmt.Errorf("获取报告缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	var report entities.StatisticsReport | ||
|  | 	err = json.Unmarshal([]byte(data), &report) | ||
|  | 	if err != nil { | ||
|  | 		return nil, fmt.Errorf("反序列化报告失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return &report, nil | ||
|  | } | ||
|  | 
 | ||
|  | // DeleteReport 删除报告缓存 | ||
|  | func (c *RedisStatisticsCache) DeleteReport(ctx context.Context, reportID string) error { | ||
|  | 	if reportID == "" { | ||
|  | 		return fmt.Errorf("报告ID不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getReportKey(reportID) | ||
|  | 	err := c.client.Del(ctx, key).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("删除报告缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // ================ 仪表板缓存 ================ | ||
|  | 
 | ||
|  | // SetDashboard 设置仪表板缓存 | ||
|  | func (c *RedisStatisticsCache) SetDashboard(ctx context.Context, dashboard *entities.StatisticsDashboard, expiration time.Duration) error { | ||
|  | 	if dashboard == nil { | ||
|  | 		return fmt.Errorf("统计仪表板不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getDashboardKey(dashboard.ID) | ||
|  | 	data, err := json.Marshal(dashboard) | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("序列化仪表板失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err = c.client.Set(ctx, key, data, expiration).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("设置仪表板缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // GetDashboard 获取仪表板缓存 | ||
|  | func (c *RedisStatisticsCache) GetDashboard(ctx context.Context, dashboardID string) (*entities.StatisticsDashboard, error) { | ||
|  | 	if dashboardID == "" { | ||
|  | 		return nil, fmt.Errorf("仪表板ID不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getDashboardKey(dashboardID) | ||
|  | 	data, err := c.client.Get(ctx, key).Result() | ||
|  | 	if err != nil { | ||
|  | 		if err == redis.Nil { | ||
|  | 			return nil, nil // 缓存未命中 | ||
|  | 		} | ||
|  | 		return nil, fmt.Errorf("获取仪表板缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	var dashboard entities.StatisticsDashboard | ||
|  | 	err = json.Unmarshal([]byte(data), &dashboard) | ||
|  | 	if err != nil { | ||
|  | 		return nil, fmt.Errorf("反序列化仪表板失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return &dashboard, nil | ||
|  | } | ||
|  | 
 | ||
|  | // DeleteDashboard 删除仪表板缓存 | ||
|  | func (c *RedisStatisticsCache) DeleteDashboard(ctx context.Context, dashboardID string) error { | ||
|  | 	if dashboardID == "" { | ||
|  | 		return fmt.Errorf("仪表板ID不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getDashboardKey(dashboardID) | ||
|  | 	err := c.client.Del(ctx, key).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("删除仪表板缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // SetDashboardData 设置仪表板数据缓存 | ||
|  | func (c *RedisStatisticsCache) SetDashboardData(ctx context.Context, userRole string, data interface{}, expiration time.Duration) error { | ||
|  | 	if userRole == "" { | ||
|  | 		return fmt.Errorf("用户角色不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getDashboardDataKey(userRole) | ||
|  | 	jsonData, err := json.Marshal(data) | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("序列化仪表板数据失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err = c.client.Set(ctx, key, jsonData, expiration).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("设置仪表板数据缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // GetDashboardData 获取仪表板数据缓存 | ||
|  | func (c *RedisStatisticsCache) GetDashboardData(ctx context.Context, userRole string) (interface{}, error) { | ||
|  | 	if userRole == "" { | ||
|  | 		return nil, fmt.Errorf("用户角色不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getDashboardDataKey(userRole) | ||
|  | 	data, err := c.client.Get(ctx, key).Result() | ||
|  | 	if err != nil { | ||
|  | 		if err == redis.Nil { | ||
|  | 			return nil, nil // 缓存未命中 | ||
|  | 		} | ||
|  | 		return nil, fmt.Errorf("获取仪表板数据缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	var result interface{} | ||
|  | 	err = json.Unmarshal([]byte(data), &result) | ||
|  | 	if err != nil { | ||
|  | 		return nil, fmt.Errorf("反序列化仪表板数据失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return result, nil | ||
|  | } | ||
|  | 
 | ||
|  | // DeleteDashboardData 删除仪表板数据缓存 | ||
|  | func (c *RedisStatisticsCache) DeleteDashboardData(ctx context.Context, userRole string) error { | ||
|  | 	if userRole == "" { | ||
|  | 		return fmt.Errorf("用户角色不能为空") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	key := c.getDashboardDataKey(userRole) | ||
|  | 	err := c.client.Del(ctx, key).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("删除仪表板数据缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // ================ 缓存键生成 ================ | ||
|  | 
 | ||
|  | // getMetricKey 获取指标缓存键 | ||
|  | func (c *RedisStatisticsCache) getMetricKey(metricID string) string { | ||
|  | 	return c.prefix + "metric:" + metricID | ||
|  | } | ||
|  | 
 | ||
|  | // getMetricsByTypeKey 获取按类型分组的指标缓存键 | ||
|  | func (c *RedisStatisticsCache) getMetricsByTypeKey(metricType string) string { | ||
|  | 	return c.prefix + "metrics:type:" + metricType | ||
|  | } | ||
|  | 
 | ||
|  | // getRealtimeMetricsKey 获取实时指标缓存键 | ||
|  | func (c *RedisStatisticsCache) getRealtimeMetricsKey(metricType string) string { | ||
|  | 	return c.prefix + "realtime:" + metricType | ||
|  | } | ||
|  | 
 | ||
|  | // getReportKey 获取报告缓存键 | ||
|  | func (c *RedisStatisticsCache) getReportKey(reportID string) string { | ||
|  | 	return c.prefix + "report:" + reportID | ||
|  | } | ||
|  | 
 | ||
|  | // getDashboardKey 获取仪表板缓存键 | ||
|  | func (c *RedisStatisticsCache) getDashboardKey(dashboardID string) string { | ||
|  | 	return c.prefix + "dashboard:" + dashboardID | ||
|  | } | ||
|  | 
 | ||
|  | // getDashboardDataKey 获取仪表板数据缓存键 | ||
|  | func (c *RedisStatisticsCache) getDashboardDataKey(userRole string) string { | ||
|  | 	return c.prefix + "dashboard:data:" + userRole | ||
|  | } | ||
|  | 
 | ||
|  | // ================ 批量操作 ================ | ||
|  | 
 | ||
|  | // BatchDeleteMetrics 批量删除指标缓存 | ||
|  | func (c *RedisStatisticsCache) BatchDeleteMetrics(ctx context.Context, metricIDs []string) error { | ||
|  | 	if len(metricIDs) == 0 { | ||
|  | 		return nil | ||
|  | 	} | ||
|  | 
 | ||
|  | 	keys := make([]string, len(metricIDs)) | ||
|  | 	for i, id := range metricIDs { | ||
|  | 		keys[i] = c.getMetricKey(id) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err := c.client.Del(ctx, keys...).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("批量删除指标缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // BatchDeleteReports 批量删除报告缓存 | ||
|  | func (c *RedisStatisticsCache) BatchDeleteReports(ctx context.Context, reportIDs []string) error { | ||
|  | 	if len(reportIDs) == 0 { | ||
|  | 		return nil | ||
|  | 	} | ||
|  | 
 | ||
|  | 	keys := make([]string, len(reportIDs)) | ||
|  | 	for i, id := range reportIDs { | ||
|  | 		keys[i] = c.getReportKey(id) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err := c.client.Del(ctx, keys...).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("批量删除报告缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // BatchDeleteDashboards 批量删除仪表板缓存 | ||
|  | func (c *RedisStatisticsCache) BatchDeleteDashboards(ctx context.Context, dashboardIDs []string) error { | ||
|  | 	if len(dashboardIDs) == 0 { | ||
|  | 		return nil | ||
|  | 	} | ||
|  | 
 | ||
|  | 	keys := make([]string, len(dashboardIDs)) | ||
|  | 	for i, id := range dashboardIDs { | ||
|  | 		keys[i] = c.getDashboardKey(id) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err := c.client.Del(ctx, keys...).Err() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("批量删除仪表板缓存失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // ================ 缓存清理 ================ | ||
|  | 
 | ||
|  | // ClearAllStatisticsCache 清理所有统计缓存 | ||
|  | func (c *RedisStatisticsCache) ClearAllStatisticsCache(ctx context.Context) error { | ||
|  | 	pattern := c.prefix + "*" | ||
|  | 	keys, err := c.client.Keys(ctx, pattern).Result() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("获取缓存键失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if len(keys) > 0 { | ||
|  | 		err = c.client.Del(ctx, keys...).Err() | ||
|  | 		if err != nil { | ||
|  | 			return fmt.Errorf("清理统计缓存失败: %w", err) | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // ClearMetricsCache 清理指标缓存 | ||
|  | func (c *RedisStatisticsCache) ClearMetricsCache(ctx context.Context) error { | ||
|  | 	pattern := c.prefix + "metric:*" | ||
|  | 	keys, err := c.client.Keys(ctx, pattern).Result() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("获取指标缓存键失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if len(keys) > 0 { | ||
|  | 		err = c.client.Del(ctx, keys...).Err() | ||
|  | 		if err != nil { | ||
|  | 			return fmt.Errorf("清理指标缓存失败: %w", err) | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // ClearRealtimeCache 清理实时缓存 | ||
|  | func (c *RedisStatisticsCache) ClearRealtimeCache(ctx context.Context) error { | ||
|  | 	pattern := c.prefix + "realtime:*" | ||
|  | 	keys, err := c.client.Keys(ctx, pattern).Result() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("获取实时缓存键失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if len(keys) > 0 { | ||
|  | 		err = c.client.Del(ctx, keys...).Err() | ||
|  | 		if err != nil { | ||
|  | 			return fmt.Errorf("清理实时缓存失败: %w", err) | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // ClearReportsCache 清理报告缓存 | ||
|  | func (c *RedisStatisticsCache) ClearReportsCache(ctx context.Context) error { | ||
|  | 	pattern := c.prefix + "report:*" | ||
|  | 	keys, err := c.client.Keys(ctx, pattern).Result() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("获取报告缓存键失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if len(keys) > 0 { | ||
|  | 		err = c.client.Del(ctx, keys...).Err() | ||
|  | 		if err != nil { | ||
|  | 			return fmt.Errorf("清理报告缓存失败: %w", err) | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | // ClearDashboardsCache 清理仪表板缓存 | ||
|  | func (c *RedisStatisticsCache) ClearDashboardsCache(ctx context.Context) error { | ||
|  | 	pattern := c.prefix + "dashboard:*" | ||
|  | 	keys, err := c.client.Keys(ctx, pattern).Result() | ||
|  | 	if err != nil { | ||
|  | 		return fmt.Errorf("获取仪表板缓存键失败: %w", err) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if len(keys) > 0 { | ||
|  | 		err = c.client.Del(ctx, keys...).Err() | ||
|  | 		if err != nil { | ||
|  | 			return fmt.Errorf("清理仪表板缓存失败: %w", err) | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } |