1package cron
2
3import (
4 "context"
5 "time"
6
7 log "github.com/charmbracelet/log/v2"
8 "github.com/robfig/cron/v3"
9)
10
11// Scheduler is a cron-like job scheduler.
12type Scheduler struct {
13 *cron.Cron
14}
15
16// cronLogger is a wrapper around the logger to make it compatible with the
17// cron logger.
18type cronLogger struct {
19 logger *log.Logger
20}
21
22// Info logs routine messages about cron's operation.
23func (l cronLogger) Info(msg string, keysAndValues ...interface{}) {
24 l.logger.Debug(msg, keysAndValues...)
25}
26
27// 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}
31
32// 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}
39
40// 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}
46
47// Start starts the Scheduler.
48func (s *Scheduler) Start() {
49 s.Cron.Start()
50}
51
52// 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), err
56}
57
58// Remove removes a job from the Scheduler.
59func (s *Scheduler) Remove(id int) {
60 s.Cron.Remove(cron.EntryID(id))
61}