86 lines
1.9 KiB
Go
86 lines
1.9 KiB
Go
package scheduler
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"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
|
|
entryIDs []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 {
|
|
if err := s.loadSchedule(); err != nil {
|
|
return err
|
|
}
|
|
s.cron.Start()
|
|
return nil
|
|
}
|
|
|
|
func (s *Scheduler) Stop() {
|
|
s.cron.Stop()
|
|
}
|
|
|
|
func (s *Scheduler) Reload() error {
|
|
for _, id := range s.entryIDs {
|
|
s.cron.Remove(id)
|
|
}
|
|
s.entryIDs = nil
|
|
return s.loadSchedule()
|
|
}
|
|
|
|
func (s *Scheduler) loadSchedule() error {
|
|
slots, err := s.repo.ListScheduleSlots()
|
|
if err != nil {
|
|
return fmt.Errorf("load schedule: %w", err)
|
|
}
|
|
if len(slots) == 0 {
|
|
fmt.Println("scheduler: no schedule configured, scraping disabled")
|
|
return nil
|
|
}
|
|
|
|
for _, slot := range slots {
|
|
// Format cron: "minute hour * * day_of_week"
|
|
spec := fmt.Sprintf("%d %d * * %d", slot.Minute, slot.Hour, slot.DayOfWeek)
|
|
id, err := s.cron.AddFunc(spec, s.run)
|
|
if err != nil {
|
|
fmt.Printf("scheduler: invalid cron spec %q: %v\n", spec, err)
|
|
continue
|
|
}
|
|
s.entryIDs = append(s.entryIDs, id)
|
|
}
|
|
|
|
fmt.Printf("scheduler: %d time slots loaded\n", len(s.entryIDs))
|
|
return nil
|
|
}
|
|
|
|
func (s *Scheduler) run() {
|
|
fmt.Println("scheduler: starting scraping cycle")
|
|
if err := s.registry.RunAll(); err != nil {
|
|
fmt.Printf("scheduler scrape error: %v\n", err)
|
|
return
|
|
}
|
|
fmt.Println("scheduler: starting AI summaries")
|
|
if err := s.pipeline.GenerateForAll(context.Background()); err != nil {
|
|
fmt.Printf("scheduler summary error: %v\n", err)
|
|
}
|
|
}
|