Files
go-synapse-backupper/pkg/adapters/scheduler/cron/cron.go
T

67 lines
1.4 KiB
Go

package cron
import (
"context"
"fmt"
"sync"
"github.com/robfig/cron/v3"
"git.tswf.io/infra/go-synapse-backupper/pkg/domain"
)
// cronScheduler wraps robfig/cron/v3 to implement domain.Scheduler.
type cronScheduler struct {
cron *cron.Cron
waitGroup sync.WaitGroup
stopCancel context.CancelFunc
stoppedCtx context.Context
}
// NewCronScheduler creates a new cron-based scheduler.
// The expr must be a valid cron expression. When WithSeconds is used
// (as in this implementation) the expression should contain six fields.
func NewCronScheduler(
expr string,
job func(),
) (
domain.Scheduler,
error,
) {
scheduler := &cronScheduler{
cron: cron.New(cron.WithSeconds()),
}
_, err := scheduler.cron.AddFunc(
expr,
func() {
scheduler.waitGroup.Add(1)
defer scheduler.waitGroup.Done()
job()
},
)
if err != nil {
return nil, fmt.Errorf("invalid cron expression %q: %w", expr, err)
}
scheduler.stoppedCtx, scheduler.stopCancel = context.WithCancel(context.Background())
return scheduler, nil
}
// Start begins executing the scheduled job.
func (s *cronScheduler) Start() {
s.cron.Start()
}
// Stop halts the scheduler and returns a context that is cancelled
// once all in-flight jobs have completed.
func (s *cronScheduler) Stop() context.Context {
s.cron.Stop()
go func() {
s.waitGroup.Wait()
s.stopCancel()
}()
return s.stoppedCtx
}