2026-05-23 12:27:44 +08:00

120 lines
2.8 KiB
Go

package storage
import (
"context"
"log/slog"
"time"
)
func (r *MySQLRepository) StartCleanup(ctx context.Context, logger *slog.Logger) {
if r.cfg.Dashboard.CleanupInterval <= 0 {
return
}
go func() {
r.cleanupOnce(ctx, logger)
ticker := time.NewTicker(r.cfg.Dashboard.CleanupInterval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
r.cleanupOnce(ctx, logger)
}
}
}()
}
func (r *MySQLRepository) cleanupOnce(ctx context.Context, logger *slog.Logger) {
rows, err := r.Cleanup(ctx)
if err != nil {
if r.metrics != nil {
r.metrics.RecordError(err)
}
logger.Error("dashboard cleanup failed", "error", err)
return
}
if r.metrics != nil {
r.metrics.RecordCleanup(rows)
}
if rows > 0 {
logger.Info("dashboard cleanup finished", "rows", rows)
}
}
func (r *MySQLRepository) Cleanup(ctx context.Context) (int64, error) {
var total int64
if r.cfg.Dashboard.DedupRetention > 0 {
cutoff := time.Now().Add(-r.cfg.Dashboard.DedupRetention)
rows, err := r.deleteLimit(ctx, `
DELETE FROM dashboard_cdc_event_dedup
WHERE created_at < ?
LIMIT ?`, cutoff, r.cfg.Dashboard.CleanupBatchSize)
if err != nil {
return total, err
}
total += rows
}
if r.cfg.Dashboard.UserMetricDays > 0 {
cutoffDate := time.Now().AddDate(0, 0, -r.cfg.Dashboard.UserMetricDays).Format("2006-01-02")
deletes := []struct {
sql string
args []interface{}
}{
{
sql: `
DELETE FROM country_dashboard_daily_user_metric
WHERE stat_date < ?
LIMIT ?`,
args: []interface{}{cutoffDate, r.cfg.Dashboard.CleanupBatchSize},
},
{
sql: `
DELETE FROM country_dashboard_period_user_metric
WHERE period_type <> 'ALL'
AND period_end_date IS NOT NULL
AND period_end_date < ?
LIMIT ?`,
args: []interface{}{cutoffDate, r.cfg.Dashboard.CleanupBatchSize},
},
{
sql: `
DELETE FROM country_dashboard_game_period_user_metric
WHERE period_type <> 'ALL'
AND period_end_date IS NOT NULL
AND period_end_date < ?
LIMIT ?`,
args: []interface{}{cutoffDate, r.cfg.Dashboard.CleanupBatchSize},
},
{
sql: `
DELETE FROM country_dashboard_recharge_detail
WHERE create_time < ?
LIMIT ?`,
args: []interface{}{cutoffDate, r.cfg.Dashboard.CleanupBatchSize},
},
}
for _, item := range deletes {
rows, err := r.execRows(ctx, item.sql, item.args...)
if err != nil {
return total, err
}
total += rows
}
}
return total, nil
}
func (r *MySQLRepository) deleteLimit(ctx context.Context, query string, args ...interface{}) (int64, error) {
return r.execRows(ctx, query, args...)
}
func (r *MySQLRepository) execRows(ctx context.Context, query string, args ...interface{}) (int64, error) {
result, err := r.db.ExecContext(ctx, query, args...)
if err != nil {
return 0, err
}
return result.RowsAffected()
}