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

83 lines
2.6 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 (
"context"
"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
}
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...")
// 为后台定时任务创建一个新的、空的 context
ctx := context.Background()
if err := s.statsService.AggregateHourlyStats(ctx); 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)
}
// 任务二:(预留) 自动健康检查
// 任务三每日执行一次的软删除Key清理
// 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...")
// [假设保留7天实际应来自配置
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.")
}