package scheduler import ( "context" "fmt" "strconv" "github.com/robfig/cron/v3" "github.com/tradarr/backend/internal/ai" "github.com/tradarr/backend/internal/models" "github.com/tradarr/backend/internal/scraper" ) type Scheduler struct { cron *cron.Cron registry *scraper.Registry pipeline *ai.Pipeline repo *models.Repository entryID cron.EntryID } func New(registry *scraper.Registry, pipeline *ai.Pipeline, repo *models.Repository) *Scheduler { return &Scheduler{ cron: cron.New(), registry: registry, pipeline: pipeline, repo: repo, } } func (s *Scheduler) Start() error { interval, err := s.getInterval() if err != nil { return err } spec := fmt.Sprintf("@every %dm", interval) s.entryID, err = s.cron.AddFunc(spec, s.run) if err != nil { return fmt.Errorf("add cron: %w", err) } s.cron.Start() fmt.Printf("scheduler started, running every %d minutes\n", interval) return nil } func (s *Scheduler) Stop() { s.cron.Stop() } func (s *Scheduler) Reload() error { s.cron.Remove(s.entryID) interval, err := s.getInterval() if err != nil { return err } spec := fmt.Sprintf("@every %dm", interval) s.entryID, err = s.cron.AddFunc(spec, s.run) return err } func (s *Scheduler) run() { fmt.Println("scheduler: running scraping cycle") if err := s.registry.RunAll(); err != nil { fmt.Printf("scheduler scrape error: %v\n", err) return } fmt.Println("scheduler: running AI summaries") if err := s.pipeline.GenerateForAll(context.Background()); err != nil { fmt.Printf("scheduler summary error: %v\n", err) } } func (s *Scheduler) getInterval() (int, error) { v, err := s.repo.GetSetting("scrape_interval_minutes") if err != nil { return 60, nil } if v == "" { return 60, nil } n, err := strconv.Atoi(v) if err != nil || n < 1 { return 60, nil } return n, nil }