Browse Source

Create/use a Job interface. Add a test.

Rob Figueiredo 13 years ago
parent
commit
bd4b092e7c
2 changed files with 57 additions and 9 deletions
  1. 17 3
      cron.go
  2. 40 6
      cron_test.go

+ 17 - 3
cron.go

@@ -16,11 +16,16 @@ type Cron struct {
 	add     chan *Entry
 }
 
+// Simple interface for submitted cron jobs.
+type Job interface {
+	Run()
+}
+
 // A cron entry consists of a schedule and the func to execute on that schedule.
 type Entry struct {
 	*Schedule
 	Next time.Time
-	Func func()
+	Job  Job
 }
 
 type byTime []*Entry
@@ -48,7 +53,16 @@ func New() *Cron {
 	}
 }
 
-func (c *Cron) Add(spec string, cmd func()) {
+// Provide a default implementation for those that want to run a simple func.
+type jobAdapter func()
+
+func (r jobAdapter) Run() { r() }
+
+func (c *Cron) AddFunc(spec string, cmd func()) {
+	c.AddJob(spec, jobAdapter(cmd))
+}
+
+func (c *Cron) AddJob(spec string, cmd Job) {
 	entry := &Entry{Parse(spec), time.Time{}, cmd}
 	select {
 	case c.add <- entry:
@@ -92,7 +106,7 @@ func (c *Cron) Run() {
 				if e.Next != effective {
 					break
 				}
-				go e.Func()
+				go e.Job.Run()
 				e.Next = e.Schedule.Next(effective)
 			}
 

+ 40 - 6
cron_test.go

@@ -22,7 +22,7 @@ func TestNoEntries(t *testing.T) {
 // Add a job, start cron, expect it runs.
 func TestAddBeforeRunning(t *testing.T) {
 	cron := New()
-	cron.Add("* * * * * ?", func() {
+	cron.AddFunc("* * * * * ?", func() {
 		cron.Stop()
 	})
 	done := startAndSignal(cron)
@@ -40,7 +40,7 @@ func TestAddWhileRunning(t *testing.T) {
 	cron := New()
 	done := startAndSignal(cron)
 	go func() {
-		cron.Add("* * * * * ?", func() {
+		cron.AddFunc("* * * * * ?", func() {
 			cron.Stop()
 		})
 	}()
@@ -57,11 +57,11 @@ func TestAddWhileRunning(t *testing.T) {
 // that the immediate entry runs immediately.
 func TestMultipleEntries(t *testing.T) {
 	cron := New()
-	cron.Add("0 0 0 1 1 ?", func() {})
-	cron.Add("* * * * * ?", func() {
+	cron.AddFunc("0 0 0 1 1 ?", func() {})
+	cron.AddFunc("* * * * * ?", func() {
 		cron.Stop()
 	})
-	cron.Add("0 0 0 31 12 ?", func() {})
+	cron.AddFunc("0 0 0 31 12 ?", func() {})
 	done := startAndSignal(cron)
 
 	select {
@@ -77,7 +77,7 @@ func TestLocalTimezone(t *testing.T) {
 	now := time.Now().Local()
 	spec := fmt.Sprintf("%d %d %d %d %d ?",
 		now.Second()+1, now.Minute(), now.Hour(), now.Day(), now.Month())
-	cron.Add(spec, func() { cron.Stop() })
+	cron.AddFunc(spec, func() { cron.Stop() })
 	done := startAndSignal(cron)
 
 	select {
@@ -87,6 +87,40 @@ func TestLocalTimezone(t *testing.T) {
 	}
 }
 
+type testRunnable struct {
+	cron *Cron
+	name string
+}
+
+func (t testRunnable) Run() {
+	t.cron.Stop()
+}
+
+// Simple test using Runnables.
+func TestRunnable(t *testing.T) {
+	cron := New()
+	cron.AddJob("0 0 0 30 Feb ?", testRunnable{cron, "job0"})
+	cron.AddJob("0 0 0 1 1 ?", testRunnable{cron, "job1"})
+	cron.AddJob("* * * * * ?", testRunnable{cron, "job2"})
+	cron.AddJob("1 0 0 1 1 ?", testRunnable{cron, "job3"})
+
+	done := startAndSignal(cron)
+	select {
+	case <-time.After(2 * time.Second):
+		t.FailNow()
+	case <-done:
+	}
+
+	// Ensure the entries are in the right order.
+	answers := []string{"job2", "job1", "job3", "job0"}
+	for i, answer := range answers {
+		actual := cron.Entries[i].Job.(testRunnable).name
+		if actual != answer {
+			t.Errorf("Jobs not in the right order.  (expected) %s != %s (actual)", answer, actual)
+		}
+	}
+}
+
 // Return a channel that signals when the cron's Start() method returns.
 func startAndSignal(cron *Cron) <-chan struct{} {
 	ch := make(chan struct{})