Skip to content

Commit bd4b092

Browse files
committed
Create/use a Job interface. Add a test.
1 parent f6244e2 commit bd4b092

File tree

2 files changed

+57
-9
lines changed

2 files changed

+57
-9
lines changed

cron.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@ type Cron struct {
1616
add chan *Entry
1717
}
1818

19+
// Simple interface for submitted cron jobs.
20+
type Job interface {
21+
Run()
22+
}
23+
1924
// A cron entry consists of a schedule and the func to execute on that schedule.
2025
type Entry struct {
2126
*Schedule
2227
Next time.Time
23-
Func func()
28+
Job Job
2429
}
2530

2631
type byTime []*Entry
@@ -48,7 +53,16 @@ func New() *Cron {
4853
}
4954
}
5055

51-
func (c *Cron) Add(spec string, cmd func()) {
56+
// Provide a default implementation for those that want to run a simple func.
57+
type jobAdapter func()
58+
59+
func (r jobAdapter) Run() { r() }
60+
61+
func (c *Cron) AddFunc(spec string, cmd func()) {
62+
c.AddJob(spec, jobAdapter(cmd))
63+
}
64+
65+
func (c *Cron) AddJob(spec string, cmd Job) {
5266
entry := &Entry{Parse(spec), time.Time{}, cmd}
5367
select {
5468
case c.add <- entry:
@@ -92,7 +106,7 @@ func (c *Cron) Run() {
92106
if e.Next != effective {
93107
break
94108
}
95-
go e.Func()
109+
go e.Job.Run()
96110
e.Next = e.Schedule.Next(effective)
97111
}
98112

cron_test.go

+40-6
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func TestNoEntries(t *testing.T) {
2222
// Add a job, start cron, expect it runs.
2323
func TestAddBeforeRunning(t *testing.T) {
2424
cron := New()
25-
cron.Add("* * * * * ?", func() {
25+
cron.AddFunc("* * * * * ?", func() {
2626
cron.Stop()
2727
})
2828
done := startAndSignal(cron)
@@ -40,7 +40,7 @@ func TestAddWhileRunning(t *testing.T) {
4040
cron := New()
4141
done := startAndSignal(cron)
4242
go func() {
43-
cron.Add("* * * * * ?", func() {
43+
cron.AddFunc("* * * * * ?", func() {
4444
cron.Stop()
4545
})
4646
}()
@@ -57,11 +57,11 @@ func TestAddWhileRunning(t *testing.T) {
5757
// that the immediate entry runs immediately.
5858
func TestMultipleEntries(t *testing.T) {
5959
cron := New()
60-
cron.Add("0 0 0 1 1 ?", func() {})
61-
cron.Add("* * * * * ?", func() {
60+
cron.AddFunc("0 0 0 1 1 ?", func() {})
61+
cron.AddFunc("* * * * * ?", func() {
6262
cron.Stop()
6363
})
64-
cron.Add("0 0 0 31 12 ?", func() {})
64+
cron.AddFunc("0 0 0 31 12 ?", func() {})
6565
done := startAndSignal(cron)
6666

6767
select {
@@ -77,7 +77,7 @@ func TestLocalTimezone(t *testing.T) {
7777
now := time.Now().Local()
7878
spec := fmt.Sprintf("%d %d %d %d %d ?",
7979
now.Second()+1, now.Minute(), now.Hour(), now.Day(), now.Month())
80-
cron.Add(spec, func() { cron.Stop() })
80+
cron.AddFunc(spec, func() { cron.Stop() })
8181
done := startAndSignal(cron)
8282

8383
select {
@@ -87,6 +87,40 @@ func TestLocalTimezone(t *testing.T) {
8787
}
8888
}
8989

90+
type testRunnable struct {
91+
cron *Cron
92+
name string
93+
}
94+
95+
func (t testRunnable) Run() {
96+
t.cron.Stop()
97+
}
98+
99+
// Simple test using Runnables.
100+
func TestRunnable(t *testing.T) {
101+
cron := New()
102+
cron.AddJob("0 0 0 30 Feb ?", testRunnable{cron, "job0"})
103+
cron.AddJob("0 0 0 1 1 ?", testRunnable{cron, "job1"})
104+
cron.AddJob("* * * * * ?", testRunnable{cron, "job2"})
105+
cron.AddJob("1 0 0 1 1 ?", testRunnable{cron, "job3"})
106+
107+
done := startAndSignal(cron)
108+
select {
109+
case <-time.After(2 * time.Second):
110+
t.FailNow()
111+
case <-done:
112+
}
113+
114+
// Ensure the entries are in the right order.
115+
answers := []string{"job2", "job1", "job3", "job0"}
116+
for i, answer := range answers {
117+
actual := cron.Entries[i].Job.(testRunnable).name
118+
if actual != answer {
119+
t.Errorf("Jobs not in the right order. (expected) %s != %s (actual)", answer, actual)
120+
}
121+
}
122+
}
123+
90124
// Return a channel that signals when the cron's Start() method returns.
91125
func startAndSignal(cron *Cron) <-chan struct{} {
92126
ch := make(chan struct{})

0 commit comments

Comments
 (0)