67 lines
1.4 KiB
Go
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
|
|
}
|