1package cron23import (4 "context"5 "time"67 "github.com/charmbracelet/log/v2"8 "github.com/robfig/cron/v3"9)1011// Scheduler is a cron-like job scheduler.12type Scheduler struct {13 *cron.Cron14}1516// cronLogger is a wrapper around the logger to make it compatible with the17// cron logger.18type cronLogger struct {19 logger *log.Logger20}2122// Info logs routine messages about cron's operation.23func (l cronLogger) Info(msg string, keysAndValues ...interface{}) {24 l.logger.Debug(msg, keysAndValues...)25}2627// Error logs an error condition.28func (l cronLogger) Error(err error, msg string, keysAndValues ...interface{}) {29 l.logger.Error(msg, append(keysAndValues, "err", err)...)30}3132// NewScheduler returns a new Cron.33func NewScheduler(ctx context.Context) *Scheduler {34 logger := cronLogger{log.FromContext(ctx).WithPrefix("cron")}35 return &Scheduler{36 Cron: cron.New(cron.WithLogger(logger)),37 }38}3940// Shutdonw gracefully shuts down the Scheduler.41func (s *Scheduler) Shutdown() {42 ctx, cancel := context.WithTimeout(s.Cron.Stop(), 30*time.Second)43 defer func() { cancel() }()44 <-ctx.Done()45}4647// Start starts the Scheduler.48func (s *Scheduler) Start() {49 s.Cron.Start()50}5152// AddFunc adds a job to the Scheduler.53func (s *Scheduler) AddFunc(spec string, fn func()) (int, error) {54 id, err := s.Cron.AddFunc(spec, fn)55 return int(id), err56}5758// Remove removes a job from the Scheduler.59func (s *Scheduler) Remove(id int) {60 s.Cron.Remove(cron.EntryID(id))61}