Files
gemini-banlancer/internal/scheduler/scheduler.go
2025-11-20 12:24:05 +08:00

91 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Filename: internal/scheduler/scheduler.go
package scheduler
import (
"gemini-balancer/internal/repository"
"gemini-balancer/internal/service"
"time"
"github.com/go-co-op/gocron"
"github.com/sirupsen/logrus"
)
type Scheduler struct {
gocronScheduler *gocron.Scheduler
logger *logrus.Entry
statsService *service.StatsService
keyRepo repository.KeyRepository
// healthCheckService *service.HealthCheckService // 健康检查任务预留
}
func NewScheduler(statsSvc *service.StatsService, keyRepo repository.KeyRepository, logger *logrus.Logger) *Scheduler {
s := gocron.NewScheduler(time.UTC)
s.TagsUnique()
return &Scheduler{
gocronScheduler: s,
logger: logger.WithField("component", "Scheduler📆"),
statsService: statsSvc,
keyRepo: keyRepo,
}
}
func (s *Scheduler) Start() {
s.logger.Info("Starting scheduler and registering jobs...")
// --- 任务注册 ---
// 使用CRON表达式精确定义“每小时的第5分钟”执行
_, err := s.gocronScheduler.Cron("5 * * * *").Tag("stats-aggregation").Do(func() {
s.logger.Info("Executing hourly request stats aggregation...")
if err := s.statsService.AggregateHourlyStats(); err != nil {
s.logger.WithError(err).Error("Hourly stats aggregation failed.")
} else {
s.logger.Info("Hourly stats aggregation completed successfully.")
}
})
if err != nil {
s.logger.Errorf("Failed to schedule [stats-aggregation]: %v", err)
}
// 任务二:(预留) 自动健康检查 (例如每10分钟一次)
/*
_, err = s.gocronScheduler.Every(10).Minutes().Tag("auto-health-check").Do(func() {
s.logger.Info("Executing periodic health check for all groups...")
// s.healthCheckService.StartGlobalCheckTask() // 伪代码
})
if err != nil {
s.logger.Errorf("Failed to schedule [auto-health-check]: %v", err)
}
*/
// [NEW] --- 任务三: 清理软删除的API Keys ---
// Executes once daily at 3:15 AM UTC.
_, err = s.gocronScheduler.Cron("15 3 * * *").Tag("cleanup-soft-deleted-keys").Do(func() {
s.logger.Info("Executing daily cleanup of soft-deleted API keys...")
// Let's assume a retention period of 7 days for now.
// In a real scenario, this should come from settings.
const retentionDays = 7
count, err := s.keyRepo.HardDeleteSoftDeletedBefore(time.Now().AddDate(0, 0, -retentionDays))
if err != nil {
s.logger.WithError(err).Error("Daily cleanup of soft-deleted keys failed.")
} else if count > 0 {
s.logger.Infof("Daily cleanup completed: Permanently deleted %d expired soft-deleted keys.", count)
} else {
s.logger.Info("Daily cleanup completed: No expired soft-deleted keys found to delete.")
}
})
if err != nil {
s.logger.Errorf("Failed to schedule [cleanup-soft-deleted-keys]: %v", err)
}
// --- 任务注册结束 ---
s.gocronScheduler.StartAsync() // 异步启动,不阻塞应用主线程
s.logger.Info("Scheduler started.")
}
func (s *Scheduler) Stop() {
s.logger.Info("Stopping scheduler...")
s.gocronScheduler.Stop()
s.logger.Info("Scheduler stopped.")
}