Пример #1
0
func StartChore(c *Chore) error {
	Logger.Debug("Re-Starting: ", c.Name)
	expr := cronexpr.MustParse(c.Sched)
	if expr.Next(time.Now()).IsZero() {
		Logger.Debug("invalid schedule", c.Sched)
		c.State = fmt.Sprintf("NOT Scheduled (invalid Schedule: %s)", c.Sched)
	} else {
		Logger.Debug("valid Schedule: ", c.Sched)
		c.Next = expr.Next(time.Now())
		dur := c.Next.Sub(time.Now())
		if dur > 0 {
			Logger.Debug("valid duration: ", dur)
			Logger.Debug("testing timer.. ")
			if c.Timer == nil {
				Logger.Debug("creating new timer ")
				c.Timer = time.AfterFunc(dur, c.Trigger) // auto go-routine'd
			} else {
				Logger.Debug("pre-existing timer found, resetting to: ", dur)
				c.Timer.Reset(dur) // auto go-routine'd
			}
			c.State = fmt.Sprintf("Scheduled: %s", c.Next.String())
		} else {
			Logger.Debug("invalid duration", dur)
			c.State = fmt.Sprintf("Halted. (invalid duration: %s)", dur)
		}
	}
	Logger.Debug("all set! Chore: ", c.Name, "scheduled at: ", c.Next)
	return nil
}
Пример #2
0
func (c *Channel) ShouldSendNowGivenTime(currentTime time.Time) bool {
	// We assume these are already sent
	if c.TimeToNotify == "@immediately" {
		return false
	}

	// the additional -1s is to make sure that the range always had 1 second.
	// example: if you specify 01:00:00, the minute before and minute after will
	// be 01:00:00 and 01:01:00. The next time computed will be an hour from now
	// (in the hourly case). This means that there's a chance that this hour we
	// never send anything. With an additional second it minimize this risk.
	//
	// Also, double sending is minimized as only 1 goroutine sends and we use a
	// delivered flag in the db.
	minuteBefore := currentTime.Add(time.Duration(-currentTime.Second()-1) * time.Second)
	minuteAfter := minuteBefore.Add(time.Minute + time.Second)
	expression := cronexpr.MustParse(c.TimeToNotify)
	nextTime := expression.Next(minuteBefore)
	if nextTime.IsZero() {
		return false
	}

	// Operator overloading is so good.
	// return (minuteBefore <= nextTime <= currentTime)
	return (nextTime.After(minuteBefore) || nextTime.Equal(minuteBefore)) && (nextTime.Before(minuteAfter) || nextTime.Equal(minuteAfter))
}
Пример #3
0
func scheduleLoop() {
	jobs := make([]*Job, 0, len(config.Schedule))
	for exprStr, cmd := range config.Schedule {
		expr := cronexpr.MustParse(exprStr)
		jobs = append(jobs, &Job{
			expr,
			cmd,
			expr.Next(time.Now()),
		})
	}

	go func() {
		for {
			<-time.Tick(time.Second)
			for _, j := range jobs {
				if time.Now().Before(j.next) {
					continue
				}
				log.Printf("Executing scheduled command '%s'...", j.cmd)
				execCmd(j.cmd)
				j.next = j.expr.Next(time.Now())
			}
		}
	}()
}
Пример #4
0
func TestZero(t *testing.T) {
	from, _ := time.Parse("2006-01-02", "2013-08-31")
	next := cronexpr.MustParse("* * * * * 1980").Next(from)
	if next.IsZero() == false {
		t.Error(`("* * * * * 1980").Next("2013-08-31").IsZero() returned 'false', expected 'true'`)
	}

	next = cronexpr.MustParse("* * * * * 2050").Next(from)
	if next.IsZero() == true {
		t.Error(`("* * * * * 2050").Next("2013-08-31").IsZero() returned 'true', expected 'false'`)
	}

	next = cronexpr.MustParse("* * * * * 2099").Next(time.Time{})
	if next.IsZero() == false {
		t.Error(`("* * * * * 2014").Next(time.Time{}).IsZero() returned 'true', expected 'false'`)
	}
}
Пример #5
0
func TestGenericFeedKilledNotificationSystem(t *testing.T) {
	fun := func(ctx *FeedContext) {
		ctx.N.Close() // easiest way to kill it
	}
	if err := runGenericFeedTest(t, fun, cronexpr.MustParse("@hourly"), 1*time.Second, 100000); err == nil {
		t.Fatal("killing notifier should have reported back an error")
	}
}
Пример #6
0
func processCronRule(rule Rule, stop chan struct{}, outCh chan messages.Message, cronRoom string) {
	nextTime := cronexpr.MustParse(rule.When).Next(time.Now())
	for {
		select {
		case <-stop:
			return
		default:
			if nextTime.Format("2006-01-02 15:04") == time.Now().Format("2006-01-02 15:04") {
				msgs := rule.Action()
				for _, msg := range msgs {
					msg.Room = cronRoom
					outCh <- msg
				}
			}
			nextTime = cronexpr.MustParse(rule.When).Next(time.Now())
			time.Sleep(2 * time.Second)
		}
	}
}
Пример #7
0
func (s *Scheduler) SubmitMultiple(newJobs []*pb.Job) {
	var jobs []*job

	for _, j := range newJobs {
		job := &job{
			id:   JobId(j.Id),
			expr: cronexpr.MustParse(j.When),
		}
		jobs = append(jobs, job)
	}
	s.queue <- jobs
}
Пример #8
0
func TestGenericFeedFiredOnRefreshAllEvent(t *testing.T) {
	done := false
	fun := func(ctx *FeedContext) {
		if !done {
			done = true
			ctx.N.Publish(core.NtRefreshAll, 0)
		}
	}
	// expect 2 events (1 due to startup, 1 due to NtRefreshAll request)
	if err := runGenericFeedTest(t, fun, cronexpr.MustParse("@hourly"), 1*time.Second, 2); err != nil {
		t.Fatal(err)
	}
}
Пример #9
0
// ExampleMustParse
func ExampleMustParse() {
	t := time.Date(2013, time.August, 31, 0, 0, 0, 0, time.UTC)
	nextTimes := cronexpr.MustParse("0 0 29 2 *").NextN(t, 5)
	for i := range nextTimes {
		fmt.Println(nextTimes[i].Format(time.RFC1123))
		// Output:
		// Mon, 29 Feb 2016 00:00:00 UTC
		// Sat, 29 Feb 2020 00:00:00 UTC
		// Thu, 29 Feb 2024 00:00:00 UTC
		// Tue, 29 Feb 2028 00:00:00 UTC
		// Sun, 29 Feb 2032 00:00:00 UTC
	}
}
Пример #10
0
// verify the schedule and start the timer
func (t *TimerCallback) Start() error {
	expr := cronexpr.MustParse(t.Schedule)
	if expr.Next(time.Now()).IsZero() {
		Logger.Debug("invalid schedule", t.Schedule)
		t.State = fmt.Sprintf("NOT Scheduled (invalid Schedule: %s)", t.Schedule)
		return fmt.Errorf("invalid schedule", t.Schedule)
	}
	t.Next = expr.Next(time.Now())
	dur := t.Next.Sub(time.Now())
	if dur > 0 {
		go t.Run(dur)
	}
	return nil
}
Пример #11
0
func BenchmarkNext(b *testing.B) {
	exprs := make([]*cronexpr.Expression, benchmarkExpressionsLen)
	for i := 0; i < benchmarkExpressionsLen; i++ {
		exprs[i] = cronexpr.MustParse(benchmarkExpressions[i])
	}
	from := time.Now()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		expr := exprs[i%benchmarkExpressionsLen]
		next := expr.Next(from)
		next = expr.Next(next)
		next = expr.Next(next)
		next = expr.Next(next)
		next = expr.Next(next)
	}
}
Пример #12
0
func (at *ActionPlan) GetNextStartTime(now time.Time) (t time.Time) {
	if !at.stCache.IsZero() {
		return at.stCache
	}
	i := at.Timing
	if i == nil || i.Timing == nil {
		return
	}
	// Normalize
	if i.Timing.StartTime == "" {
		i.Timing.StartTime = "00:00:00"
	}
	if len(i.Timing.Years) > 0 && len(i.Timing.Months) == 0 {
		i.Timing.Months = append(i.Timing.Months, 1)
	}
	if len(i.Timing.Months) > 0 && len(i.Timing.MonthDays) == 0 {
		i.Timing.MonthDays = append(i.Timing.MonthDays, 1)
	}
	at.stCache = cronexpr.MustParse(i.Timing.CronString()).Next(now)
	return at.stCache
}
Пример #13
0
func TestNextN_every5min(t *testing.T) {
	expected := []string{
		"Mon, 2 Sep 2013 08:45:00",
		"Mon, 2 Sep 2013 08:50:00",
		"Mon, 2 Sep 2013 08:55:00",
		"Mon, 2 Sep 2013 09:00:00",
		"Mon, 2 Sep 2013 09:05:00",
	}
	from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:32")
	result := cronexpr.MustParse("*/5 * * * *").NextN(from, uint(len(expected)))
	if len(result) != len(expected) {
		t.Errorf(`MustParse("*/5 * * * *").NextN("2013-09-02 08:44:30", 5):\n"`)
		t.Errorf(`  Expected %d returned time values but got %d instead`, len(expected), len(result))
	}
	for i, next := range result {
		nextStr := next.Format("Mon, 2 Jan 2006 15:04:05")
		if nextStr != expected[i] {
			t.Errorf(`MustParse("*/5 * * * *").NextN("2013-09-02 08:44:30", 5):\n"`)
			t.Errorf(`  result[%d]: expected "%s" but got "%s"`, i, expected[i], nextStr)
		}
	}
}
Пример #14
0
func TestNextN(t *testing.T) {
	expected := []string{
		"Sat, 30 Nov 2013 00:00:00",
		"Sat, 29 Mar 2014 00:00:00",
		"Sat, 31 May 2014 00:00:00",
		"Sat, 30 Aug 2014 00:00:00",
		"Sat, 29 Nov 2014 00:00:00",
	}
	from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:30")
	result := cronexpr.MustParse("0 0 * * 6#5").NextN(from, uint(len(expected)))
	if len(result) != len(expected) {
		t.Errorf(`MustParse("0 0 * * 6#5").NextN("2013-09-02 08:44:30", 5):\n"`)
		t.Errorf(`  Expected %d returned time values but got %d instead`, len(expected), len(result))
	}
	for i, next := range result {
		nextStr := next.Format("Mon, 2 Jan 2006 15:04:15")
		if nextStr != expected[i] {
			t.Errorf(`MustParse("0 0 * * 6#5").NextN("2013-09-02 08:44:30", 5):\n"`)
			t.Errorf(`  result[%d]: expected "%s" but got "%s"`, i, expected[i], nextStr)
		}
	}
}
Пример #15
0
func main() {
	app := cli.NewApp()
	app.Version = "0.1.0"
	app.Name = "cronexpr"
	app.Usage = "convert cron expression and get next occurance"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "unix, u",
			Value: "",
			Usage: "from specific unix timestamp",
		},
		cli.StringFlag{
			Name:  "format, f",
			Value: "",
			Usage: "format options see http://strftime.org/",
		},
		cli.StringFlag{
			Name:  "next, n",
			Value: "",
			Usage: "n next time stamps",
		},
		cli.StringFlag{
			Name:  "utc",
			Value: "false",
			Usage: "n next time stamps",
		},
	}
	app.Action = func(c *cli.Context) {
		cron := ""
		if len(c.Args()) > 0 {
			cron = c.Args()[0]
		} else {
			panic("missing cron expression")
		}

		from := time.Now()
		if c.String("unix") != "" {
			u, err := strconv.ParseInt(c.String("unix"), 10, 64)
			if err != nil {
				panic(err)
			}
			from = time.Unix(u, 0)
		}
		if c.BoolT("utc") {
			from = from.UTC()
		}

		if c.String("next") != "" {
			n, err := strconv.ParseInt(c.String("next"), 10, 64)
			if err != nil {
				panic(err)
			}
			result := cronexpr.MustParse(cron).NextN(from, uint(n))
			for _, next := range result {
				out := strconv.FormatInt(next.Unix(), 10)
				if c.String("format") != "" {
					out = strftime.Format(c.String("format"), next)
				}
				fmt.Println(out)
			}
		} else {
			result := cronexpr.MustParse(cron).Next(from)
			out := strconv.FormatInt(result.Unix(), 10)
			if c.String("format") != "" {
				out = strftime.Format(c.String("format"), result)
			}
			fmt.Println(out)
		}
	}

	app.Run(os.Args)
}
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("Check", func() {
	var checkCmd *exec.Cmd

	BeforeEach(func() {
		checkCmd = exec.Command(checkPath)
	})

	Context("MustParse", func() {
		It("can parse crontab expressions", func() {
			expr := cronexpr.MustParse("* * * * 0-5")
			Expect(expr).ToNot(BeNil())
		})
	})

	Context("when a crontab expression is specified", func() {
		var request models.CheckRequest
		var response models.CheckResponse
		var session *gexec.Session

		BeforeEach(func() {
			request = models.CheckRequest{
				Source: models.Source{
					Location: "America/New_York",
				},
			}
Пример #17
0
func TestGenericHourlyFeed(t *testing.T) {
	if err := runGenericFeedTest(t, nil, cronexpr.MustParse("@hourly"), 1*time.Second, 1); err != nil {
		t.Fatal(err)
	}
}
Пример #18
0
func TestGenericFeedRefreshInterval(t *testing.T) {
	oncePerSecond := "* * * * * * *"
	if err := runGenericFeedTest(t, nil, cronexpr.MustParse(oncePerSecond), 3*time.Second, 2); err != nil {
		t.Fatal(err)
	}
}
Пример #19
0
func BenchmarkParse(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = cronexpr.MustParse(benchmarkExpressions[i%benchmarkExpressionsLen])
	}
}
Пример #20
0
func main() {
	flag.Parse()
	runtime.GOMAXPROCS(*threads)

	var cron *cronexpr.Expression
	if *update != "" {
		cron = cronexpr.MustParse(*update)
	}

	var db oui.DynamicDB
	url := ""
	fileName := ""
	var err error

	if strings.HasPrefix(*ouiFile, "http") {
		url = *ouiFile
		if url == "http" {
			url = "http://standards-oui.ieee.org/oui.txt"
		}
		log.Println("Downloading new Db from: " + url)
		db, err = oui.OpenHttp(url)
		if err != nil {
			log.Fatalf("Error downloading:%s", err.Error())
		}
	} else {
		fileName = *ouiFile
		log.Println("Opening database from: " + fileName)
		db, err = oui.OpenFile(fileName)
		if err != nil {
			log.Fatalf("Error updating file:%s", err.Error())
		}
	}
	log.Printf("Database generated at %s\n", db.Generated().Local().String())

	// Start updater if needed.
	if cron != nil {
		go func() {
			for {
				// Sleep until next update
				next := cron.Next(time.Now())
				log.Println("Next update: " + next.String())
				time.Sleep(next.Sub(time.Now()))
				if url != "" {
					log.Println("Updating db from: " + url)
					err := oui.UpdateHttp(db, url)
					if err != nil {
						log.Printf("Error downloading update:%s", err.Error())
					} else {
						log.Println("Updated Successfully")
					}
				} else {
					log.Println("Updating db with file: " + fileName)
					err := oui.UpdateFile(db, fileName)
					if err != nil {
						log.Printf("Error loading update:%s", err.Error())
					} else {
						log.Println("Updated Successfully")
					}
				}
			}
		}()
	}

	// We dereference this to avoid a pretty big penalty under heavy load.
	prettyL := *pretty

	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		var mac string
		var hw *oui.HardwareAddr

		// Prepare the response and queue sending the result.
		res := &Response{}

		defer func() {
			var j []byte
			var err error
			if prettyL {
				j, err = json.MarshalIndent(res, "", "  ")
			} else {
				j, err = res.MarshalJSON()
			}
			if err != nil {
				log.Fatal(err)
			}
			w.Write(j)
		}()

		// Set headers
		if *originPolicy != "" {
			w.Header().Set("Access-Control-Allow-Origin", *originPolicy)
		}
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Last-Modified", db.Generated().Format(http.TimeFormat))

		// Find Mac
		mac = req.URL.Query().Get("mac")
		if mac == "" {
			mac = strings.Trim(req.URL.Path, "/")
		}
		hw, err := oui.ParseMac(mac)
		if err != nil {
			res.Error = err.Error()
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		entry, err := db.LookUp(*hw)
		if err != nil {
			if err == oui.ErrNotFound {
				res.Error = "not found in db"
				w.WriteHeader(http.StatusNotFound)
				return
			}
			w.WriteHeader(http.StatusInternalServerError)
			res.Error = err.Error()
			return
		}
		res.Data = entry
	})

	log.Println("Listening on " + *listen)
	log.Fatal(http.ListenAndServe(*listen, nil))
}
Пример #21
0
// Cron returns a CronSchedule using the cron expression giving as parameter of the function.
func Cron(expression string) CronSchedule {
	expr := cronexpr.MustParse(expression)
	return CronSchedule{
		Expression: expr,
	}
}