1// Package cron provides scheduled task management functionality.
2package cron
3
4import (
5 "context"
6 "time"
7
8 "github.com/charmbracelet/log/v2"
9 "github.com/robfig/cron/v3"
10)
11
12// Scheduler is a cron-like job scheduler.
13type Scheduler struct {
14 *cron.Cron
15}
16
17// cronLogger is a wrapper around the logger to make it compatible with the
18// cron logger.
19type cronLogger struct {
20 logger *log.Logger
21}
22
23// Info logs routine messages about cron's operation.
24func (l cronLogger) Info(msg string, keysAndValues ...interface{}) {
25 l.logger.Debug(msg, keysAndValues...)
26}
27
28// Error logs an error condition.
29func (l cronLogger) Error(err error, msg string, keysAndValues ...interface{}) {
30 l.logger.Error(msg, append(keysAndValues, "err", err)...)
31}
32
33// NewScheduler returns a new Cron.
34func NewScheduler(ctx context.Context) *Scheduler {
35 logger := cronLogger{log.FromContext(ctx).WithPrefix("cron")}
36 return &Scheduler{
37 Cron: cron.New(cron.WithLogger(logger)),
38 }
39}
40
41// Shutdown gracefully shuts down the Scheduler.
42func (s *Scheduler) Shutdown() {
43 ctx, cancel := context.WithTimeout(s.Stop(), 30*time.Second)
44 defer func() { cancel() }()
45 <-ctx.Done()
46}
47
48// Start starts the Scheduler.
49func (s *Scheduler) Start() {
50 s.Cron.Start()
51}
52
53// AddFunc adds a job to the Scheduler.
54func (s *Scheduler) AddFunc(spec string, fn func()) (int, error) {
55 id, err := s.Cron.AddFunc(spec, fn)
56 return int(id), err
57}
58
59// Remove removes a job from the Scheduler.
60func (s *Scheduler) Remove(id int) {
61 s.Cron.Remove(cron.EntryID(id))
62}