Skip to content

Commit 36cd85f

Browse files
DojetoJohnRoesler
andauthored
feat:custom-cron interface for own custom cron implimentation (#834)
* feat:custom-cron interface for own custom cron implimentation * feat: tranfer the custom cron implimentation in the job options * Apply suggestions from code review * Apply suggestions from code review * Apply suggestions from code review * Apply suggestions from code review * Apply suggestions from code review --------- Co-authored-by: John Roesler <[email protected]>
1 parent 1fe8c5c commit 36cd85f

File tree

1 file changed

+70
-13
lines changed

1 file changed

+70
-13
lines changed

job.go

+70-13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type internalJob struct {
2424
id uuid.UUID
2525
name string
2626
tags []string
27+
cron Cron
2728
jobSchedule
2829

2930
// as some jobs may queue up, it's possible to
@@ -104,6 +105,20 @@ type limitRunsTo struct {
104105
runCount uint
105106
}
106107

108+
// -----------------------------------------------
109+
// -----------------------------------------------
110+
// --------------- Custom Cron -------------------
111+
// -----------------------------------------------
112+
// -----------------------------------------------
113+
114+
// Cron defines the interface that must be
115+
// implemented to provide a custom cron implementation for
116+
// the job. Pass in the implementation using the JobOption WithCronImplementation.
117+
type Cron interface {
118+
IsValid(crontab string, location *time.Location, now time.Time) error
119+
Next(lastRun time.Time) time.Time
120+
}
121+
107122
// -----------------------------------------------
108123
// -----------------------------------------------
109124
// --------------- Job Variants ------------------
@@ -116,29 +131,37 @@ type JobDefinition interface {
116131
setup(j *internalJob, l *time.Location, now time.Time) error
117132
}
118133

119-
var _ JobDefinition = (*cronJobDefinition)(nil)
134+
// Default cron implementation
120135

121-
type cronJobDefinition struct {
122-
crontab string
123-
withSeconds bool
136+
func newDefaultCronImplementation(withSeconds bool) Cron {
137+
return &defaultCron{
138+
withSeconds: withSeconds,
139+
}
124140
}
125141

126-
func (c cronJobDefinition) setup(j *internalJob, location *time.Location, now time.Time) error {
142+
var _ Cron = (*defaultCron)(nil)
143+
144+
type defaultCron struct {
145+
cronSchedule cron.Schedule
146+
withSeconds bool
147+
}
148+
149+
func (r *defaultCron) IsValid(crontab string, location *time.Location, now time.Time) error {
127150
var withLocation string
128-
if strings.HasPrefix(c.crontab, "TZ=") || strings.HasPrefix(c.crontab, "CRON_TZ=") {
129-
withLocation = c.crontab
151+
if strings.HasPrefix(crontab, "TZ=") || strings.HasPrefix(crontab, "CRON_TZ=") {
152+
withLocation = crontab
130153
} else {
131154
// since the user didn't provide a timezone default to the location
132155
// passed in by the scheduler. Default: time.Local
133-
withLocation = fmt.Sprintf("CRON_TZ=%s %s", location.String(), c.crontab)
156+
withLocation = fmt.Sprintf("CRON_TZ=%s %s", location.String(), crontab)
134157
}
135158

136159
var (
137160
cronSchedule cron.Schedule
138161
err error
139162
)
140163

141-
if c.withSeconds {
164+
if r.withSeconds {
142165
p := cron.NewParser(cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
143166
cronSchedule, err = p.Parse(withLocation)
144167
} else {
@@ -150,8 +173,32 @@ func (c cronJobDefinition) setup(j *internalJob, location *time.Location, now ti
150173
if cronSchedule.Next(now).IsZero() {
151174
return ErrCronJobInvalid
152175
}
176+
r.cronSchedule = cronSchedule
177+
return nil
178+
}
153179

154-
j.jobSchedule = &cronJob{cronSchedule: cronSchedule}
180+
func (r *defaultCron) Next(lastRun time.Time) time.Time {
181+
return r.cronSchedule.Next(lastRun)
182+
}
183+
184+
// default cron job implimentation
185+
var _ JobDefinition = (*cronJobDefinition)(nil)
186+
187+
type cronJobDefinition struct {
188+
crontab string
189+
cron Cron
190+
}
191+
192+
func (c cronJobDefinition) setup(j *internalJob, location *time.Location, now time.Time) error {
193+
if j.cron != nil {
194+
c.cron = j.cron
195+
}
196+
197+
if err := c.cron.IsValid(c.crontab, location, now); err != nil {
198+
return err
199+
}
200+
201+
j.jobSchedule = &cronJob{crontab: c.crontab, cronSchedule: c.cron}
155202
return nil
156203
}
157204

@@ -163,8 +210,8 @@ func (c cronJobDefinition) setup(j *internalJob, location *time.Location, now ti
163210
// `CRON_TZ=America/Chicago * * * * *`
164211
func CronJob(crontab string, withSeconds bool) JobDefinition {
165212
return cronJobDefinition{
166-
crontab: crontab,
167-
withSeconds: withSeconds,
213+
crontab: crontab,
214+
cron: newDefaultCronImplementation(withSeconds),
168215
}
169216
}
170217

@@ -608,6 +655,15 @@ func WithName(name string) JobOption {
608655
}
609656
}
610657

658+
// WithCronImplementation sets the custom Cron implementation for the job.
659+
// This is only utilized for the CronJob type.
660+
func WithCronImplementation(c Cron) JobOption {
661+
return func(j *internalJob, _ time.Time) error {
662+
j.cron = c
663+
return nil
664+
}
665+
}
666+
611667
// WithSingletonMode keeps the job from running again if it is already running.
612668
// This is useful for jobs that should not overlap, and that occasionally
613669
// (but not consistently) run longer than the interval between job runs.
@@ -818,7 +874,8 @@ type jobSchedule interface {
818874
var _ jobSchedule = (*cronJob)(nil)
819875

820876
type cronJob struct {
821-
cronSchedule cron.Schedule
877+
crontab string
878+
cronSchedule Cron
822879
}
823880

824881
func (j *cronJob) next(lastRun time.Time) time.Time {

0 commit comments

Comments
 (0)