Explorar o código

cron Start(), Stop(), Add()

Rob Figueiredo %!s(int64=13) %!d(string=hai) anos
pai
achega
260ece1235
Modificáronse 1 ficheiros con 46 adicións e 35 borrados
  1. 46 35
      cron.go

+ 46 - 35
cron.go

@@ -3,7 +3,7 @@
 package cron
 
 import (
-	_ "sort"
+	"sort"
 	"time"
 )
 
@@ -13,6 +13,7 @@ import (
 type Cron struct {
 	Entries []*Entry
 	stop    chan struct{}
+	add     chan *Entry
 }
 
 // A cron entry consists of a schedule and the func to execute on that schedule.
@@ -31,52 +32,62 @@ func (s byTime) Less(i, j int) bool { return s[i].Next.Before(s[j].Next) }
 func New() *Cron {
 	return &Cron{
 		Entries: nil,
+		add:     make(chan *Entry),
 		stop:    make(chan struct{}),
 	}
 }
 
 func (c *Cron) Add(spec string, cmd func()) {
-	c.Entries = append(c.Entries, &Entry{Parse(spec), time.Time{}, cmd})
+	entry := &Entry{Parse(spec), time.Time{}, cmd}
+	select {
+	case c.add <- entry:
+		// The run loop accepted the entry, nothing more to do.
+		return
+	default:
+		// No one listening to that channel, so just add to the array.
+		c.Entries = append(c.Entries, entry)
+	}
 }
 
-// func (c *Cron) Run() {
-// 	if len(c.Entries) == 0 {
-// 		return
-// 	}
-
-// 	var (
-// 		now = time.Now()
-// 		effective = now
-// 	)
+func (c *Cron) Start() {
+	// Figure out the next activation times for each entry.
+	now := time.Now()
+	for _, entry := range c.Entries {
+		entry.Next = entry.Schedule.Next(now)
+	}
 
-// 	// Figure out the next activation times for each entry.
-// 	for _, entry := range c.Entries {
-// 		entry.Next = entry.Schedule.Next(now)
-// 	}
-// 	sort.Sort(byTime(c.Entries))
+	for {
+		// Determine the next entry to run.
+		sort.Sort(byTime(c.Entries))
 
-// 	for {
-// 		// Sleep until the next job needs to get run.
-// 		effective = c.Entries[0].Next
-// 		time.Sleep(effective.Sub(now))
+		var effective time.Time
+		if len(c.Entries) == 0 {
+			// If there are no entries yet, just sleep - it still handles new entries
+			// and stop requests.
+			effective = now.AddDate(10, 0, 0)
+		} else {
+			effective = c.Entries[0].Next
+		}
 
-// 		now = time.Now()
+		select {
+		case now = <-time.After(effective.Sub(now)):
+			// Run every entry whose next time was this effective time.
+			for _, e := range c.Entries {
+				if e.Next != effective {
+					break
+				}
+				go e.Func()
+				e.Next = e.Schedule.Next(effective)
+			}
 
-// 		// Run every entry whose next time was this effective time.
-// 		// Find how long until the next entry needs to get run.
-// 		for _, e := range c.Entries {
-// 			if e.Next != effective {
-// 				break
-// 			}
-// 			// TODO: Check that it's at least one
-// 			go c.Func()
-// 		}
+		case newEntry := <-c.add:
+			c.Entries = append(c.Entries, newEntry)
 
-// 		case <-c.stop:
-// 			return
-// 		}
-// 	}
-// }
+		case <-c.stop:
+			return
+		}
+	}
+}
 
 func (c Cron) Stop() {
 	c.stop <- struct{}{}