cron.go

 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}